Anotación de tipo de retorno vacío de Python

108

En Python 3.x, es común usar la anotación de tipo de retorno de una función, como:

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

¿Cuál es la anotación correcta para el tipo "vacío"?

Estoy considerando 3 opciones:

  1. def foo() -> None:
    • no es lógico en mi opinión, porque Noneno es un tipo,
  2. def foo() -> type(None):
    • utilizando la mejor sintaxis que conozco para obtener NoneType,
  3. def foo():
    • omitir información explícita del tipo de retorno.

La opción 2 me parece la más lógica, pero ya he visto algunos casos de 1.

Tregoreg
fuente
11
FWIW, Python no tiene funciones con voidtipo de retorno. Cualquier función (o rama en una función) sin un returnretorno explícito None. Supongo que el OP entiende que, este comentario es principalmente para el beneficio de los futuros lectores ...
PM 2 Ring
Bueno, esta pregunta no es tan popular como "¿por qué mi función devuelve None en Python?" (Hice esta pregunta), por lo que probablemente la mayoría de los lectores ya conozcan el comportamiento predeterminado. El dilema 1 vs 2 se resuelve en la respuesta. Pero ¿y 3? Para los "procedimientos" prefiero la opción 3, sin desorden inútil (después de todo, esta función no devuelve nada).
Tomasz Gandor
@TomaszGandor De acuerdo. Cuando una función o un método no contiene una declaración de retorno, no es necesario especificar su tipo de retorno.
Jeyekomon

Respuestas:

121

Esto es directamente de la documentación de PEP 484 - Type Hints :

Cuando se usa en una sugerencia de tipo, la expresión Nonese considera equivalente a type(None).

Y, como puede ver, la mayoría de los ejemplos se utilizan Nonecomo tipo de retorno.

AKS
fuente
22
Para aclarar, elija la opción 1 anterior.
Adam Nelson
6
¿Qué pasa con el tipo NoReturn python.org/dev/peps/pep-0484/#the-noreturn-type ?
asmaier
12
@asmaier de acuerdo con esta pregunta que cita PEP 484 - El NoReturn tipo Type Hints se usa "... para anotar funciones que nunca regresan normalmente. Por ejemplo, una función que genera incondicionalmente una excepción ..."
Rodrigo Laguna
38

TLDR: el equivalente idiomático de una voidanotación de tipo de retorno es -> None.

def foo() -> None:
    ...

Esto coincide con lo que evalúa una función sin returno simplemente returncon None.

def void_func():  # unannotated void function
    pass

print(void())  # None

Omitir el tipo de devolución no significa que no haya un valor de devolución. Según PEP 484 :

Para una función marcada, la anotación predeterminada para argumentos y para el tipo de retorno es Any.

Esto significa que el valor se considera de tipo dinámico y admite estáticamente cualquier operación . Ese es prácticamente el significado opuesto de void.


Las sugerencias de tipo en Python no requieren estrictamente tipos reales. Por ejemplo, las anotaciones pueden usar cadenas de nombres de tipo: Union[str, int], Union[str, 'int'], 'Union[str, int]'y varias variantes son equivalentes.

De manera similar, Nonese considera que la anotación de tipo significa "es de NoneType". Esto se puede usar no solo para tipos de devolución, aunque lo verá con más frecuencia allí:

bar : None

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

Esto también se aplica a los tipos genéricos. Por ejemplo, puede usar Nonein Generator[int, None, None]para indicar que un generador no toma ni devuelve valores.


Aunque PEP 484 sugiere que eso Nonesignifica type(None), no debe utilizar la última forma explícitamente. La especificación de sugerencia de tipo no incluye ninguna forma de type(...). Esta es técnicamente una expresión en tiempo de ejecución, y su soporte depende totalmente del verificador de tipos. El mypyproyecto está considerando la posibilidad de eliminar el soporte para type(None)y sacarlo de 484 también.

¿O tal vez deberíamos actualizar PEP 484 para que no sugiera que type(None)es válido como tipo, y Nonees la única ortografía correcta? Debe haber una, y preferiblemente solo una, forma obvia de hacerlo, etc.

--- JukkaL, 18 de mayo de 2018

MisterMiyagi
fuente
4
Gran agradecimiento por explicar por qué la tercera opción en realidad no es función nula en absoluto.
никта