Python 3.6 está a punto de ser lanzado. PEP 494 - Python 3.6 Release Schedule menciona finales de diciembre, así que revisé las novedades de Python 3.6 para ver que mencionan las anotaciones de variables :
PEP 484 introdujo el estándar para anotaciones de tipo de parámetros de función, también conocido como sugerencias de tipo. Este PEP agrega sintaxis a Python para anotar los tipos de variables, incluidas las variables de clase y las variables de instancia:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: Dict[str, int] = {}
Al igual que para las anotaciones de funciones, el intérprete de Python no asigna ningún significado particular a las anotaciones de variables y solo las almacena en un atributo especial
__annotations__
de una clase o módulo. A diferencia de las declaraciones de variables en lenguajes de tipado estático, el objetivo de la sintaxis de anotación es proporcionar una manera fácil de especificar metadatos de tipo estructurado para herramientas y bibliotecas de terceros a través del árbol de sintaxis abstracta y el__annotations__
atributo.
Entonces, por lo que leí, son parte de las sugerencias de tipo que provienen de Python 3.5, descritas en ¿Qué son las sugerencias de tipo en Python 3.5 ?
Sigo el ejemplo de captain: str
y class Starship
, pero no estoy seguro del último: ¿Cómo se primes: List[int] = []
explica? ¿Está definiendo una lista vacía que solo permitirá números enteros?
fuente
primes: List[int] = []
es solo una lista vacía comoprimes = []
. La diferencia es que usted está afirmando queprimes
está destinado a contener soloint
mensajes de correo electrónico y las aplicaciones de terceros pueden escribir verificar su programa para verificar esta afirmación, pero cuando ejecuta el código en cualquier intérprete de Python, eso es lo mismo que escribirprimes = []
, y por lo tantoprimes: List[int] = []; primes.append("string")
sigue siendo válido.Respuestas:
Todo entre
:
y=
es una sugerencia de tipo, porprimes
lo que de hecho se define comoList[int]
, e inicialmente se establece en una lista vacía (ystats
es un diccionario vacío inicialmente, definido comoDict[str, int]
).List[int]
yDict[str, int]
no forman parte de la siguiente sintaxis, sin embargo, estos ya estaban definidos en Python 3.5 typing hints PEP. El 3,6 PEP 526 - Sintaxis de las variables Anotaciones propuesta sólo se define la sintaxis para fijar los mismos consejos a variables; antes, solo podía adjuntar sugerencias de tipo a las variables con comentarios (por ejemploprimes = [] # List[int]
).Ambos
List
yDict
son tipos genéricos , lo que indica que tiene una lista o mapeo de diccionario con contenido específico (concreto).Porque
List
, solo hay un 'argumento' (los elementos en la[...]
sintaxis), el tipo de cada elemento en la lista. ParaDict
, el primer argumento es el tipo de clave y el segundo el tipo de valor. Por lo tanto, todos los valores de laprimes
lista son números enteros y todos los pares clave-valor delstats
diccionario son(str, int)
pares, asignando cadenas a números enteros.Vea las definiciones
typing.List
ytyping.Dict
, la sección sobre Genéricos , así como PEP 483 - The Theory of Type Hints .Al igual que las sugerencias de tipo en funciones, su uso es opcional y también se consideran anotaciones (siempre que haya un objeto al que adjuntarlas, por lo tanto, globales en módulos y atributos en clases, pero no locales en funciones) que puede introspectar a través del
__annotations__
atributo. Puede adjuntar información arbitraria a estas anotaciones, no está estrictamente limitado a escribir información de sugerencia.Es posible que desee leer la propuesta completa ; contiene algunas funciones adicionales más allá de la nueva sintaxis; especifica cuándo se evalúan tales anotaciones, cómo hacer una introspección y cómo declarar algo como un atributo de clase frente a un atributo de instancia, por ejemplo.
fuente
obj.__annotations__
atributo)?Las anotaciones variables son solo el siguiente paso de los
# type
comentarios, tal como se definieron enPEP 484
; el fundamento de este cambio se destaca en la sección respectiva del PEP 526 .Entonces, en lugar de insinuar el tipo con:
primes = [] # type: List[int]
Se introdujo una nueva sintaxis para permitir anotar directamente el tipo con una asignación del formulario:
que, como señaló @Martijn, denota una lista de enteros mediante el uso de tipos disponibles
typing
e inicializándola en una lista vacía.El primer cambio introducido fue una nueva sintaxis que le permite anotar un nombre con un tipo, ya sea de forma independiente después del
:
carácter u opcionalmente anotar al mismo tiempo que le asigna un valor:annotated_assignment_stmt ::= augtarget ":" expression ["=" expression]
Entonces el ejemplo en cuestión:
primes: List[int] = [ ] # ^ ^ ^ # augtarget | | # expression | # expression (optionally initialize to empty list)
También se introdujeron cambios adicionales junto con la nueva sintaxis; Los módulos y clases ahora tienen un
__annotations__
atributo (como las funciones han tenido desde PEP 3107 - Anotaciones de funciones ) en el que se adjunta el tipo de metadatos:from typing import get_type_hints # grabs __annotations__
Ahora
__main__.__annotations__
contiene los tipos declarados:>>> from typing import List, get_type_hints >>> primes: List[int] = [] >>> captain: str >>> import __main__ >>> get_type_hints(__main__) {'primes': typing.List<~T>[int]}
captain
actualmente no se mostraráget_type_hints
porqueget_type_hints
solo devuelve tipos a los que también se puede acceder en un módulo; es decir, primero necesita un valor:>>> captain = "Picard" >>> get_type_hints(__main__) {'primes': typing.List<~T>[int], 'captain': <class 'str'>}
Se
print(__annotations__)
mostrará el uso ,'captain': <class 'str'>
pero en realidad no debería acceder__annotations__
directamente.Del mismo modo, para las clases:
>>> get_type_hints(Starship) ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})
Donde
ChainMap
se usa a para tomar las anotaciones para una clase dada (ubicadas en el primer mapeo) y todas las anotaciones definidas en las clases base encontradas en sumro
(mapeos consecuentes,{}
para objeto).Junto con la nueva sintaxis,
ClassVar
se ha agregado un nuevo tipo para denotar variables de clase. Sí,stats
en su ejemplo es en realidad una variable de instancia , no unClassVar
.Al igual que con las sugerencias de tipo de
PEP 484
, estos son completamente opcionales y son de uso principal para las herramientas de verificación de tipos (y cualquier otra cosa que pueda construir basándose en esta información). Será provisional cuando se lance la versión estable de Python 3.6, por lo que podrían agregarse pequeños ajustes en el futuro.fuente