Новая подборка советов про Python и программирование из моего авторского канала @pythonetc.

Порядок блоков except имеет значение: если исключение может быть поймано несколькими блоками, то его поймает верхний блок. Этот код не будет работать так, как задумано:
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 IndexError не будет работать, потому что IndexError является подклассом LookupError. Более конкретное исключение всегда должно находиться выше:
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 поддерживает параллельное присваивание. Это означает, что все переменные изменяются сразу после вычисления всех выражений. Более того, вы можете использовать любое выражение, поддерживающее присваивание, а не только переменные:
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 не будет автоматически использовать сложение с отрицательным числом вместо вычитания. Рассмотрим пример:
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'
Этот код не работает:
v1 = Velocity(20_000_000) v2 = Velocity(10_000_000) print(v1 - v2) # TypeError: unsupported operand type(s) for -: 'Velocity' and 'Velocity
Забавно, но этот код работает:
v1 = Velocity(20_000_000) v2 = Velocity(10_000_000) print(v1 +- v2) # 10022302 m/s

Эта часть написана Telegram-пользователем orsinium.
Функция не могут быть одновременно генератором и обычной функцией. Если в теле функции используется yield, то она превращается в генератор:
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)) # []
Однако обычная функция может вернуть другой итератор:
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]
А такой вариант может быть полезен в случаях с простыми выражениями-генераторами:
def zeros(*, count: int, lazy: bool): if lazy: return (0 for _ in range(count)) return [0] * count

При создании generator comprehension необходимо использовать скобки:
>>> 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>
Однако их можно опустить, если comprehension является единственный аргумент функции:
>>> list((x**x for x in range(4))) [1, 1, 4, 27] >>> list(x**x for x in range(4)) [1, 1, 4, 27]
Это не верно для функций, у которых несколько аргументов:
>>> 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
ссылка на оригинал статьи https://habr.com/ru/company/mailru/blog/487728/
Добавить комментарий