Питон развивается очень быстро, запомнить сразу все его новые фишки сложно. Сегодня я бы хотел показать несколько интересных фишек из 3.8 и 3.9, которыми не все пользуются. Детали я оставлю для документации, покажу лишь примеры для затравки. Весь код запускался в Jupyter Notebook.
Union оператор для dict
d1 = {"spam": 1, "person": 3}
d2 = {"test": 2}
dict(**d2, **d1)
>>> {'test': 2, 'spam': 1, 'person': 3}
А так же можно получить значения которых нет во втором dict:
d = {'spam': 1, 'eggs': 2, 'cheese': 3}
e = {'cheese': 'cheddar', 'aardvark': 'Ethel'}
d | e
>>> {'spam': 1, 'eggs': 2, 'cheese': 'cheddar', 'aardvark': 'Ethel'}
Или обновить сразу значение dict:
d |= e
d
>>> {'spam': 1, 'eggs': 2, 'cheese': 'cheddar', 'aardvark': 'Ethel'}
remove prefixes and suffixes
Следующая вещь, которая мне понравилась это
remove prefixes and suffixes. Не уверен что очень полезная фишка, но может сократить размер кода в некоторых местах:
"test_name".removeprefix("test_")
>>> ‘name’
"name_test".removesuffix('_test')
>>> ‘name’
Assignment expressions
В свое время наделавшая шуму фича Assignment expressions. Для определенных целей может быть полезна, я пока не определился нравится ли она мне.
if (n := len("test_long_string")) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
>>> List is too long (16 elements, expected <= 10)
positional only parameters
Очень интересная фича для более строгой работы с аргументами, благодаря которой можно добиться большей читаемости кода:
def f(a, b, /, c, d, e, *, f):
print(a, b, c, d, e, f)
f(1,2,3,4,5,6)
>>> TypeError: f() takes 5 positional arguments but 6 were given
f(1,2,3,4,5,f=6)
>>> 1 2 3 4 5 6
f(a=1,2,3,4,5,f=6)
>>> SyntaxError: positional argument follows keyword argument
f(1,2,c=3,d=4,e=5,f=6)
>>> 1 2 3 4 5 6
f-strings support =
Маленькая но приятная фишка. Добавляем в f-string = и получаем магию:
user = 'kris'
member_since = date(2000, 7, 31)
f'{user} {member_since=}'
>>> 'kris member_since=datetime.date(2000, 7, 31)'
f'{user=} {member_since=}'
>>> "user='kris' member_since=datetime.date(2000, 7, 31)"
Мелочь а приятно.
asyncio.run()
Ну и конечно новый способ запускать асинхронный код на выполнение, который стал проще и безопаснее. Все детали лучше посмотреть в документации, но как было и стало конечно внушает оптимизм.
Стало:
import asyncio
async def main():
await asyncio.sleep(0)
return 42
asyncio.run(main())
Было:
import asyncio
async def main():
await asyncio.sleep(0)
return 42
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(main())
finally:
asyncio.set_event_loop(None)
loop.close()