Аннотация типа возвращаемого значения void в Python

118

В python 3.x обычно используется аннотация типа возвращаемого значения функции, например:

def foo() -> str:
    return "bar"

Какая аннотация подходит для типа "void"?

Рассматриваю 3 варианта:

  1. def foo() -> None:
    • не логично ИМО, потому что Noneэто не тип,
  2. def foo() -> type(None):
    • используя лучший синтаксис, который я знаю для получения NoneType,
  3. def foo():
    • опускать явную информацию о типе возврата.

Вариант 2 кажется мне наиболее логичным, но я уже видел несколько примеров 1.

Tregoreg
источник
12
FWIW, Python не имеет функций с voidвозвращаемым типом. Любая функция (или ветвь в функции) без явного значения returnвернется None. Я предполагаю, что OP понимает это, этот комментарий в основном для будущих читателей ...
PM 2Ring
Что ж, этот вопрос не так популярен, как «почему моя функция в Python не возвращает None?» (Я придумал этот вопрос), поэтому, вероятно, большинство читателей уже знают поведение по умолчанию. В ответе решена дилемма 1 против 2. А как насчет 3? Для «процедур» я бы предпочел вариант 3, без лишнего беспорядка (в конце концов, эта функция ничего не возвращает).
Томаш Гандор
@TomaszGandor Согласен. Когда функция или метод не содержат оператора возврата, нет необходимости указывать его тип возврата.
Jeyekomon

Ответы:

128

Это прямо из документации PEP 484 - Type Hints :

При использовании в подсказке типа выражение Noneсчитается эквивалентным type(None).

И, как вы можете видеть, в большинстве примеров используется Noneтип возвращаемого значения.

AKS
источник
22
Чтобы уточнить, выберите вариант 1 выше.
Адам Нельсон
6
А как насчет типа NoReturn python.org/dev/peps/pep-0484/#the-noreturn-type ?
asmaier
13
@asmaier в соответствии с этим вопросом, который цитирует PEP 484 - Тип подсказок NoReturn типа используется «... для аннотирования функций, которые никогда не возвращаются нормально. Например, функция, которая безусловно вызывает исключение ...»
Родриго Лагуна,
40

TL; DR: идиоматический эквивалент voidаннотации возвращаемого типа - -> None.

def foo() -> None:
    ...

Это соответствует тому, что функция без returnили просто returnоценивает None.

def void_func():  # unannotated void function
    pass

print(void())  # None

Отсутствие возвращаемого типа не означает, что возвращаемого значения нет. Согласно PEP 484 :

Для проверенной функции аннотация по умолчанию для аргументов и для типа возвращаемого значения - Any.

Это означает, что значение считается динамически типизированным и статически поддерживает любую операцию . Это практически противоположное значение void.


Подсказка типов в Python не требует строго фактических типов. Например, аннотации могут использовать строки имен типа: Union[str, int], Union[str, 'int'], 'Union[str, int]'а также различные варианты эквивалентны.

Точно так же аннотация типа Noneсчитается означающей «имеет NoneType». Это можно использовать не только для возвращаемых типов, хотя чаще всего вы увидите это там:

bar : None

def foo(baz: None) -> None:
    return None

Это также относится к универсальным типам. Например, вы можете использовать Nonein, Generator[int, None, None]чтобы указать, что генератор не принимает и не возвращает значения.


Несмотря на то, что PEP 484 предполагает, что это Noneозначает type(None), вы не должны использовать последнюю форму явно. Спецификация подсказки типов не включает никаких форм type(...). Технически это выражение времени выполнения, и его поддержка полностью зависит от средства проверки типов. mypyПроект рассматривает возможность удалить поддержку для type(None)и удалить его из 484 , а также.

Или, может быть, нам следует обновить PEP 484, чтобы не предполагать, что type(None)это действительный тип и Noneявляется единственно правильным написанием? Должен быть один - и желательно только один - очевидный способ сделать это и т. Д.

--- JukkaL, 18 мая 2018 г.

Мистер Мияги
источник
4
Огромный привет за объяснение, почему 3-й вариант вообще не является недействительной функцией.
никта