@Pythonetc kompilasi, Januari 2020



Pilihan baru tips dan pemrograman Python dari umpan @pythonetc saya.

โ† Publikasi sebelumnya


Urutan blok exceptpenting: jika pengecualian dapat ditangkap oleh beberapa blok, maka blok atas akan menangkapnya. Kode ini tidak akan berfungsi sebagaimana dimaksud:

import logging

def get(storage, key, default):
    try:
        return storage[key]
    except LookupError:
        return default
    except IndexError:
        return get(storage, 0, default)
    except TypeError:
        logging.exception('unsupported key')
        return default

print(get([1], 0, 42))  # 1
print(get([1], 10, 42))  # 42
print(get([1], 'x', 42))  # error msg, 42

except IndexErrortidak akan berfungsi karena ini IndexErroradalah subkelas LookupError. Pengecualian yang lebih spesifik harus selalu lebih tinggi:

import logging

def get(storage, key, default):
    try:
        return storage[key]
    except IndexError:
        return get(storage, 0, default)
    except LookupError:
        return default
    except TypeError:
        logging.exception('unsupported key')
    return default

print(get([1], 0, 42))  # 1
print(get([1], 10, 42))  # 1
print(get([1], 'x', 42))  # error msg, 42


Python mendukung penugasan bersamaan. Ini berarti bahwa semua variabel berubah segera setelah mengevaluasi semua ekspresi. Selain itu, Anda dapat menggunakan ekspresi apa pun yang mendukung penugasan, dan bukan hanya variabel:

def shift_inplace(lst, k):
    size = len(lst)
    lst[k:], lst[0:k] = lst[0:-k], lst[-k:]

lst = list(range(10))

shift_inplace(lst, -3)
print(lst)
# [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]

shift_inplace(lst, 5)
print(lst)
# [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]


Python tidak akan secara otomatis menggunakan penambahan angka negatif daripada mengurangi. Pertimbangkan sebuah contoh:

class Velocity:
    SPEED_OF_LIGHT = 299_792_458

    def __init__(self, amount):
        self.amount = amount

    def __add__(self, other):
        return type(self)(
            (self.amount + other.amount) /
            (
                1 +
                self.amount * other.amount /
                self.SPEED_OF_LIGHT ** 2
            )
        )

    def __neg__(self):
        return type(self)(-self.amount)

    def __str__(self):
        amount = int(self.amount)
        return f'{amount} m/s'

Kode ini tidak berfungsi:

v1 = Velocity(20_000_000)
v2 = Velocity(10_000_000)

print(v1 - v2)
# TypeError: unsupported operand type(s) for -: 'Velocity' and 'Velocity


Lucu, tetapi kode ini berfungsi:

v1 = Velocity(20_000_000)
v2 = Velocity(10_000_000)

print(v1 +- v2)
# 10022302 m/s


Bagian ini ditulis oleh pengguna Telegram. orsinium.

Suatu fungsi tidak bisa menjadi generator dan fungsi biasa. Jika digunakan di tubuh fungsi yield, maka itu berubah menjadi generator:

def zeros(*, count: int, lazy: bool):
        if lazy:
            for _ in range(count):
                yield 0
            else:
                return [0] * count

zeros(count=10, lazy=True)
# <generator object zeros at 0x7ff0062f2a98>

zeros(count=10, lazy=False)
# <generator object zeros at 0x7ff0073da570>

list(zeros(count=10, lazy=False))
# []

Namun, fungsi reguler dapat mengembalikan iterator lain:

def _lazy_zeros(*, count: int):
    for _ in range(count):
        yield 0
    
def zeros(*, count: int, lazy: bool):
    if lazy:
        return _lazy_zeros(count=count)
    return [0] * count

zeros(count=10, lazy=True)
# <generator object _lazy_zeros at 0x7ff0062f2750>

zeros(count=10, lazy=False)
# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Dan opsi ini dapat berguna dalam kasus dengan generator ekspresi sederhana:

def zeros(*, count: int, lazy: bool):
    if lazy:
        return (0 for _ in range(count))
    return [0] * count


Saat membuat pemahaman generator, Anda harus menggunakan tanda kurung:

>>> g = x**x for x in range(10)
    File "<stdin>", line 1
        g = x**x for x in range(10)
            ^
SyntaxError: invalid syntax
>>> g = (x**x for x in range(10))
>>> g
<generator object <genexpr> at 0x7f90ed650258>


Namun, mereka dapat dihilangkan jika pemahaman adalah satu-satunya argumen ke fungsi:

>>> list((x**x for x in range(4)))
[1, 1, 4, 27]
>>> list(x**x for x in range(4))
[1, 1, 4, 27]


Ini tidak benar untuk fungsi yang memiliki banyak argumen:

>>> print((x**x for x in range(4)), end='\n')
<generator object <genexpr> at 0x7f90ed650468>
>>>
>>>
>>> print(x**x for x in range(4), end='\n')
    File "<stdin>", line 1
SyntaxError: Generator expression must be parenthesized if not sole argument

Source: https://habr.com/ru/post/undefined/


All Articles