Как в Python 3.9 исправили декораторы и улучшили словари

Перевод статьи «How Python 3.9 fixed decorators and improved dictionaries».

Python 3.9 был выпущен в 2020 году, и новая версия была оснащена новыми интересными функциями. Однако пока далеко не все знают о них, к сожалению, и не все используют новые фичи Python 3.9 при написании кода. Сегодня мы поговорим о том, как в Python 3.9 исправили декораторы и улучшили словари.

python

Объединение словарей

Допустим, у вас есть словарь со значениями по умолчанию, и вы хотите обновить его параметры. До Python 3.9 лучшим вариантом было скопировать словарь по умолчанию, а затем использовать метод .update().

Python 3.9 представил в словарях оператор объединения:

defaults = dict(who="someone", where="somewhere")
params = dict(where="our town", when="today")
defaults | params

# Результат 
{'who': 'someone', 'where': 'our town', 'when': 'today'}

Обратите внимание, что порядок имеет значение. В данном случае значение where из params переопределяет значение по умолчанию, как и должно быть.

Удаление префиксов

Если вы выполняете специальный синтаксический анализ или очистку текста с помощью Python, то раньше вам нужно было писать подобный код:

def process_pricing_line(line):
    if line.startswith("pricing:"):
        return line[len("pricing:"):]
    return line
process_pricing_line("pricing:20")

# Результат: '20'

Однако такой код подвержен ошибкам. Например, если вы случайно по ошибке скопировали строку в следующую строку, цена станет 0 вместо 20. И это может произойти совершенно незаметно.

Начиная с Python 3.9, строки имеют метод .removeprefix():

"pricing:20".removeprefix("pricing:")

# Результат: '20'

Произвольные выражения декораторов

Раньше было очень мало документации о том, какие выражения разрешены в декораторе. Это очень затрудняло понимание, как корректнее их использовать. Например, следующий код является правильным и рабочим:

@item.thing
def foo():
    pass

И такой тоже является правильным:

@item.thing()
def foo():
    pass

Однако следующий, казалось бы, очень похожий на предыдущие аналоги код, уже выдает синтаксическую ошибку:

@item().thing
def foo():
    pass

Начиная с Python 3.9, в качестве декоратора может использоваться любое выражение:

from unittest import mock

item = mock.MagicMock()

@item().thing
def foo():
    pass
print(item.return_value.thing.call_args[0][0])

Хотя сохранение простых выражений в строке декоратора по-прежнему является хорошей практикой, теперь это решение зависит от человека, а не от парсера Python.

Добро пожаловать в 2021

Сегодня мы поговорили о том, как в Python 3.9 исправили декораторы и улучшили словари. И хотя Python 3.9 был выпущен около года назад, некоторые функции, впервые появившиеся в этой версии, круты – и, к сожалению,  используются недостаточно. Добавьте их в свой инструментарий, если вы еще этого не сделали.