В Python снова предлагают операторы ?. и ?? для работы с None

1 ноября 2026 года Марк Мюллер (Marc Mueller) снова вынес на обсуждение два черновика: PEP 823 и PEP 824. Оба нацелены на Python 3.16, спонсор обоих Гвидо ван Россум, и оба про одно и то же: как короче и надёжнее работать со значениями, которые могут оказаться None.

Если вы пишете на Python бэкенд, скрипты для админки или разбираете JSON из чужих API, то знаете эти лесенки из if x is not None. В других языках их давно заменяют операторы ?. и ??: они есть в TypeScript, JavaScript, C#, Kotlin, Swift, Dart и PHP. Теперь их снова предлагают для Python, на этот раз двумя отдельными документами.

PEP 823: обращение к атрибуту, которое не падает на None

Первый документ добавляет два оператора: ?. для обращения к атрибуту и ?[ ] для обращения по индексу или ключу. Логика простая: Python вычисляет то, что стоит слева, и если там None, вся остальная цепочка пропускается и результатом становится None. Если слева обычный объект, всё работает как с привычной точкой или квадратными скобками.

Пример из самого PEP. Сейчас, чтобы достать имя покупателя, у которого может не быть ни карточки клиента, ни пользователя, пишут так:

def get_customer_name(data):
    customer = data.customer
    if customer is not None:
        user = customer.user
        if user is not None:
            return user.name.lower()
    return None

С новым оператором это одна строка:

def get_customer_name(data):
    return data.customer?.user?.name.lower()

Для разбора JSON пригодится вариант со скобками: data.get("customer")?["user"]?["name"]. Как только где-то в цепочке встретится None, всё выражение вернёт None, а не упадёт с TypeError.

Важно понимать, чего эти операторы не делают. Они реагируют только на None и не прячут другие ошибки. Если атрибута нет вовсе, вы всё равно получите AttributeError, а если в словаре нет ключа, то KeyError. Для отсутствующих ключей по-прежнему нужен dict.get(). Присваивать через них нельзя: a?.b = 1 даст SyntaxError. И скобки обрывают цепочку: a?.b.c вернёт None, а (a?.b).c упадёт, если a равно None.

PEP 824: значение по умолчанию вместо None

Второй документ предлагает оператор ?? и его вариант с присваиванием ??=. Запись a ?? b возвращает a, если оно не None, и b в противном случае. Запись a ??= b присваивает значение, только если в a сейчас None.

Главное отличие от привычного or в том, что or заменяет любое «ложное» значение: ноль, пустую строку, пустой список. Из-за этого age = user_age or "unknown" превратит возраст 0 в «unknown». Оператор ?? смотрит только на None, поэтому ноль и пустая строка останутся как есть.

def show_user_age(user):
    age = user.age ?? "unknown"
    print(f"The user age is {age}")

def add_default_user(users=None):
    users ??= []
    users.append(create_default_user())
    return users

Второй пример закрывает старую проблему с изменяемыми значениями по умолчанию в аргументах функций: вместо трёх строк с if users is None остаётся одна. Приоритет у ?? ниже, чем у or и and, так что a ?? b or c читается как a ?? (b or c). Автор сам советует ставить скобки, когда эти операторы смешиваются в одном выражении.

Почему это обсуждают уже десять лет

Идея не новая. Все четыре оператора предлагал ещё PEP 505 в 2015 году, но его отложили. Новые документы делят идею пополам, и каждый можно принять независимо от другого. Как пишет Real Python, в обсуждениях на discuss.python.org набралось почти двести сообщений, и мнения разделились. Сторонникам ?? нравится, что он реагирует только на None. Пол Мур (Paul Moore), давний мейнтейнер pip, написал, что поведение ?. для него не очевидно, а часть участников считает такие операторы не в духе Python.

Сами PEP разбирают эти возражения отдельно: что знак вопроса легко не заметить в длинной строке, что такие операторы поощряют злоупотребление None, что можно обойтись match, try или библиотекой вроде glom. Автор PEP 823 прямо пишет, что больше одного ?. в цепочке нужно редко, и если их много, стоит подумать о структуре данных или вспомогательной функции.

По графику Python 3.16 новые возможности можно добавлять до первой беты 4 мая 2027 года, финальный релиз запланирован на 5 октября 2027 года. Вторая альфа выйдет 10 ноября. Пока оба документа в статусе черновика, решения Руководящего совета (Steering Council) нет.

Как попробовать операторы уже сейчас

Для обоих PEP есть эталонная реализация в форке CPython и онлайн-демо. Это сборка Python на WebAssembly прямо в браузере: можно написать код в редакторе или открыть интерактивную консоль и проверить, как ведут себя ?., ?[ ], ?? и ??=. В обычных версиях Python, включая альфу 3.16, такой код пока даёт SyntaxError.

Если операторы примут, код, который вытаскивает данные из вложенных объектов и ответов API, станет заметно короче, а ошибки с нулём и пустой строкой, которые сейчас тихо съедает or, станет проще избежать. Если у вас есть мнение, сейчас самое время высказать его в обсуждении: решение по Python 3.16 ещё не принято.

Источники и ссылки


Комментарии загружаются…