Аналитика
Новый синтаксис старой команды with в Python 3.10

Новый синтаксис старой команды with в Python 3.10

Как же долго моё чувство прекрасного страдало… Но в Python 3.10 появился новый парсер синтаксических конструкций Python!

Больше новшеств Python 3.10.

С новым парсером в Python 3.10 появилась возможность разбора не-LL(1) грамматик, что позволило исправить давнишние проблемы в синтаксисе. В частности, я всегда советовал студентам и коллегам использовать скобки для группировки длинных команд вместо обратной черты \.

Часто код получается более выразительным и менее уродливым (что для меня также важно). Так, например код:

    very_long_operation_result = some_variable[very_important_index] + \
        some_another_variable + and_here_we_call_function(with_wrong_param, \
        and_this_param, one_more_function(once_again_param, its_never_enough) \
        and_param_which_should_not_be_used) + one_more_variable

Можно, на мой взгляд, написать более читаемо:

    very_long_operation_result = (
        some_variable[very_important_index]
        + some_another_variable
        - and_here_we_call_function(
            with_this_param,
            and_this_param,
            one_more_function(once_again_param, its_never_enough)
        )
        + one_more_variable
    )

Можете считать меня перфекционистом (что точно не про меня) и занудой (этого немного есть)… Но я довольно много раз получал весёлые баги от того, что не мог с первого раза прочитать нормально подобную формулу. Или же найти ошибку в знаке - тот минус в 4-ой строке почему-то был плюсом, а функция возвращала ненулевой результат в редких случаях.

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

Изображение Python 3.11. Что нового?

Новый нормальный контекстный менеджер with

Так вот я к чему… Даже с моими доводами выше, я иной раз получал ответ: "PEP-8 разрешает, да и с конструкцией with так нельзя". Нельзя было, ибо парсер не позволял! А сейчас можно:

    with (CtxManager() as example):
        ...

    with (
        CtxManager1(),
        CtxManager2()
    ):
        ...

    with (
        CtxManager1() as example1,
        CtxManager2() as example2
    ):
        ...

Все эти замечательные скобочки теперь работают и при использовании контекстных менеджеров с with!

В примерах также есть и иные подходы. Я не считаю их также удобными:

    with (CtxManager1() as example,
          CtxManager2()):
        ...

    with (CtxManager1(),
          CtxManager2() as example):
        ...

Поясню. Отступы в Python имеют довольно важное значение. По большей части это "Провалиться на один уровень вложенности/логики вглубь". А различный код типа:

    def function():
        def some_internal_function():
            and_here_we_define_variable = (lets_calc_something
                                            + do_not_stop_please
                                            + if_you_dont_understand
                                            + my_pain)
            some_thing_else()
            ...

Такой код я называю "топором", ибо похоже: вот у нас рукоятка, вот пошла "борода". Помимо чисто геометрического отвращения, отвращения логического ("отступ = логический уровень") я испытываю боль при доработке такого кода: а если нужно ещё добавить вызов функции для прибавления к значению? В diff будет куча строчек, хотя я добавил по факту одну...

В общем, теперь можно писать более единообразно и правильно (на мой взгляд). Кто знает, может по такой радости и вернусь программировать на Python!