Обзор Python 3.8
Релиз Python 3.8 намечен на октябрь 2019 года, но уже сейчас у каждого есть возможность пощупать набор новых фишек языка. Пока пишу этот пост, на официальном сайте доступна версия python 3.8b2.
Итак, что же нам готовит релиз грядущий?
f-string =
Теперь выводить debug информацию стало ещё проще и красивее. Достаточно в f-string передать знак =:
>> a = 123
>> b = 456
>> print(f'{a=} and {b=}')
a=123 and b=456
Assignment Expressions или :=, он же walrus operator
Легендарный PEP572 из-за которого Гвидо сложил полномочия диктатора Python. Оператор выполняет присваивание значения переменной в выражении. Например, вам хочется проверить есть ли ключ в словаре, а также присвоить значение этого ключа переменной. В версиях Python до 3.8 необходимо сделать:
params = {'foo': 'bar'}
x = params.get('foo')
if x:
print(x)
В версии 3.8 код выглядит чуть компактнее:
params = {'foo': 'bar'}
if x := params.get('foo'):
print(x)
Positional-only arguments
В python 3 в далёком 2006 году появились keyword-only arguments (PEP3102). Их задача заключается в навязывании передачи аргументов функции или методу по ключу после символа *
def test(a, b, *, key1, key2):
pass
test(1,2,3,4)
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
test(1,2,3,4)
TypeError: test() takes 2 positional arguments but 4 were given</module></pyshell#7>
Интерпретатор сообщает нам, что функция принимает только 2 позиционных аргумента, но передано было 4. Чтобы он не ругался, функцию необходимо вызывать так:
test(1, 2, key1=3, key2=4)
В python 3.8 появилась возможность задавать передачу аргументов исключительно согласно их позиции. В отличие от keyword-only arguments, все аргументы обязаны быть переданы согласно позиции:
def position_only(a, b, c, d=0, /):
pass
position_only(1, 2, 3) # OK
position_only(1, 2, c=3) # вызов такой функции провоцирует исключение
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
position_only(1,2,c=3)
TypeError: position_only() got some positional-only arguments passed as keyword arguments: 'c'</module></pyshell#11>
Общая память для IPC
Для межпроцессорного взаимодействия в python 3.8 появилась общая память. Раньше, чтобы передавать данные между процессами внутренний механизм подразумевал сериализацию и десериализацию объекта и отправку данных в сокет. С использованием механизма ОС по выделению общей памяти, отпадает необходимость взаимодействия через диск или сокет, а это даёт значительный рост к производительности. В пакете multiprocessing появился модуль shared_memory. Пример использования общей памяти между двумя разными процессами:
from multiprocessing import shared_memory
a = shared_memory.ShareableList(range(5))
print(a.shm.name)
>>> 'wnsm_bd6b5302'
Открываем другой shell и считываем данные из общей памяти:
from multiprocessing import shared_memory
b = shared_memory.ShareableList(name='wnsm_bd6b5302')
print(b)
>>> ShareableList([0, 1, 2, 3, 4], name='wnsm_bd6b5302')
TypedDict
Появилась возможность указывать тип значений у словарей с фиксированным количеством строковых ключей. Например:
from typing import TypedDict
class Movie(TypedDict):
title: str
year: int
movie: Movie = {
'title': 'Catch me if you can',
'year': 2002
}
Класс Movie можно использовать в аннотациях:
from typing import List
def my_function(films: List[Movie]):
pass
final
Те, кто знаком с Java сразу понимают что такое final. То, что помечено final не должно изменяться во время жизненного цикла скрипта.
from typing import Final, final
birth_year: Final = 1989
birth_year = 1901 # вот тут IDE или type checker вроде mypy должен ругаться
Классы, помеченные декоратором final, не должны быть унаследованы:
@final
class FinalClass:
pass
class InheritedFromFinal(FinalClass): # нельзя наследовать класс FinalClass
pass
Также можно формально запретить переопределение метода в дочернем классе:
class MyClass:
@final
def prohibited(self):
pass
class SecondClass(MyClass):
def prohibited(self): # вот тут type checker должен дико материться
pass
Это далеко не все фишечки в новой версии Python. Более подробно о новинках можно узнать по ссылке.