TGViewer
Alinsky.tech Alinsky.tech @alinsky_tech · 129 subscribers
Post #56 999
Типизация опциональности в питоне.

Этот спор древен примерно также как и вопрос: -табы или пробелы? Однажды из-за этого я умудрился даже с коллегами поругаться, поэтому давайте разберёмся из-за чего бывают конфликты у задротов 🤔

Суть в следующем: допустим у нас есть произвольный тип T, но мы хотим задать такой тайпхинт, чтобы иметь возможность оставить переменную с типом Т неопределенной. Как мы это сделаем?

Существует 3 решения:

a: T = None
b: Optional[T] = None
c: Union[T, None] = None


Далее подробнее про каждый из вариантов.

Вариант A:
Самый простой и некоторые линтеры вполне корректно его обработают, подменив на вариант B, но заточенные на типизацию вроде mypy и pyright дадут вам смачного леща, потому что ну а какого хрена вы присвоили неверный тип, а??

Вариант B:
Самый распространенный вариант и куда лучше чем A, но идейно неверный. Представьте следующее выражение:
def f(b: Optional[T]): pass
На уровне логики аргумент b является опциональным, но в то же время, если мы его не передадим в функцию, то программа упадет с ошибкой, т к фактически на уровне кода b является обязательным. Какая-то суперпозиция получается 🤔 Дело в том, что на самом деле понятия опционального аргумента и аргумента, способного принимать None - это совершенно разные и не связанные понятия, которые ошибочно были склеины в классе Optional. В помойку его!

Вариант C:
Фактически это аналог записи вида c: T | None появившейся с версии 3.10, но если вы используете версию младше или пишете обратносовместимый код, то это тот самый вариант, который верен и на уровне логики и на уровне кода. Его я и считаю правильным использовать.

Давайте рассмотрим способы возможного применения последнего варианта в разрезе опциональности. Допустим у нас есть класс пользователя:

class User:
    id: int
    name: Union[str, None]
    last_name: Union[str, None] = None


Из записи атрибутов следует следующая логика:
* id - атрибут типа int, который должен быть обязательно указан.
* name - атрибут, который может быть как str, так и None, но должен быть обязательно указан.
* last_name - атрибут, который может быть как str, так и None, но является опциональным т к он уже имеет дефолтное значение.

Хинт: для того чтоб быстро зарефачить проект с варианта B на вариант C можно воспользоваться утилитой no-optional.

Установка:
pip install no-optional

Рефакторинг одного файла:
no_optional <filename>

А следующей командой можно отредактировать весь проект целиком:
find <project_folder> -iname "*.py" | xargs python -m no_optional

#dev
  • 👍 6
  • 🔥 2
  • ❤ 1
More from @alinsky_tech
  1. Jun 1, 2026Про мои планы на лето рассказывает
  2. May 24, 2026Да и не только космоса…
  3. May 5, 2026В 1937 по личному указу гитлера был основан Volkswagen. На днях их крупный заводов начала…
  4. May 1, 2026photo post
  5. Apr 28, 2026Про его историю однозначно должны снять фильм… https://www.youtube.com/watch?v=30rqdk4iZ5I
  6. Apr 20, 2026У меня включается отцовский инстинкт к Диане 🤗
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →