Подробности на английском языке.
Ниже переведено только необходимое, можете добавлять в комментариях.
Моржовый оператор
Выражения присваивания пришли в Python с оператором "морж", то есть :=
. Данный оператор позволяет вам присваивать значения переменной как часть выражения. Основной выигрыш применения этого оператора состоит в сокращении количества строк, которые вам потребуется написать.
Раньше писали так:
line = f.readline()
while line:
... # process line
line = f.readline()
теперь можно так:
while line := f.readline():
... # process line
Кратко, но некоторые говорят, что первый вариант понятнее.
Только позиционные аргументы
Специальный маркер /
можно использовать для определения аргументов метода, чтобы указать, что этот функционал принимает только позиционные аргументы слева от маркера. Именованные аргументы доступны через маркер *
и добавление нового маркера /
для позиционных аргументов способствует целостности языка и созданию устойчивых API.
Рассмотрим пример:
def pow(x, y, z=None, /):
r = x ** y
if z is not None:
r %= z
return r
Маркер /
означает, что передать значения для x
, y
и z
можно только позиционно, не используя именованные аргументы. Вот подробности:
>>> pow(2, 10) # правильно
>>> pow(2, 10, 17) # правильно
>>> pow(x=2, y=10) # неправильно, выбросит TypeError
>>> pow(2, 10, z=17) # неправильно, выбросит TypeError
Подробности смотрите в PEP-570.
F-строки поддерживают =
Программисты часто используют отладку принтами. В старые времена это было очень просто:
print "foo=", foo, "bar=", bar
Использование F-строк чуть упростило процесс:
print(f"foo={foo} bar={bar}")
Но всё равно приходится писать одно и то же, но с применением =
, в виде f'{expr=}'
, всё становится очень просто:
print(f"{foo=} {bar=}")
Функция reversed
теперь работает со словарями
Начиная с версии 3.7 словари хранят порядок вставки ключей. Встроенная функция reversed
теперь может быть использована для доступа к словарю в обратном порядке, подобно OrderedDict
:
>>> my_dict = dict(a=1, b=2)
>>> list(reversed(my_dict))
['b', 'a']
>>> list(reversed(my_dict.items()))
[('b', 2), ('a', 1)]
Починили распаковку итераций
Это непреднамеренное поведение существовало с версии 3.2, который запрещал распаковку итераций без круглых скобок в операторах return
и yield
.
Раньше можно было так:
def foo():
rest = (4, 5, 6)
t = 1, 2, 3, *rest
return t
но нельзя так:
def baz():
rest = (4, 5, 6)
return 1, 2, 3, *rest
def baz():
rest = (4, 5, 6)
yield 1, 2, 3, *rest
Теперь это починили ;)
Добавили производительности
По сравнению с версией 3.7:
- Метод
operator.itemgetter()
стал быстрее на 33%. - Поиск полей в
collections. namedtuple()
теперь выполняется более чем в два раза быстрее, что делает их самой быстрой формой поиска переменных экземпляра в Python. - Конструктор списка не перераспределяет внутренний буфер элемента, если итерируемый вход имеет известную длину, то есть реализует
len
. Это делает созданный список в среднем на 12% меньше. - Запись переменных класса теперь в два раза быстрее.
- Вызов некоторых простых встроенных модулей и методов теперь на 20-50% быстрее. Снижены накладные расходы на преобразование аргументов в эти методы.
uuid.UUID
теперь использует слоты, чтобы уменьшить потребляемый объём памяти.
AsyncIO стал стабильным
Упростился запуск
Функция 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()
Асинхронная консоль
Команда python -m asyncio
запускает асинхронный интерпретатор, что позволяет быстро экспериментировать с await
кодом, больше не надо использовать для этого функцию asyncio.run()
:
$ python -m asyncio
asyncio REPL 3.8.0
Use "await" directly instead of "asyncio.run()".
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> await asyncio.sleep(10, result='hello')
hello
Коллекции
Метод _asdict()
класса collections.namedtuple()
теперь возвращает словарь вместо OrderedDict
, так как обычные словари сохраняют порядок ключей, начиная с версии 3.7.