¿Qué son las anotaciones variables en Python 3.6?
python-3.x annotations (2)
¿Qué son las anotaciones variables?
Las anotaciones variables son solo el siguiente paso de
# type
comentarios
# type
, tal como se definieron en
PEP 484
;
El fundamento de este cambio se destaca en la
sección respectiva de PEP 526
.
Entonces, en lugar de insinuar el tipo con:
primes = [] # type: List[int]
Se introdujo una nueva sintaxis para permitir la anotación directa del tipo con una asignación del formulario:
primes: List[int] = []
que, como señaló @Martijn, denota una lista de enteros utilizando los tipos disponibles al
typing
e inicializándolos en una lista vacía.
¿Qué cambios trae?
El primer cambio introducido fue una
nueva sintaxis
que le permite anotar un nombre con un tipo, ya sea 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 las clases ahora tienen un atributo
__annotations__
(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
no se mostrará actualmente a través de
get_type_hints
porque
get_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''>}
El uso de
print(__annotations__)
mostrará
''captain'': <class ''str''>
pero realmente no deberías acceder a
__annotations__
directamente.
Del mismo modo, para las clases:
>>> get_type_hints(Starship)
ChainMap({''stats'': typing.Dict<~KT, ~VT>[str, int]}, {})
Donde se utiliza un
ChainMap
para capturar las anotaciones para una clase dada (ubicada en la primera asignación) y todas las anotaciones definidas en las clases base encontradas en su
mro
(asignaciones consecuentes,
{}
para el objeto).
Junto con la nueva sintaxis, se ha agregado un nuevo tipo
ClassVar
para denotar variables de clase.
Sí, las
stats
en su ejemplo son en realidad una
variable de instancia
, no una
ClassVar
.
¿Me veré obligado a usarlo?
Al igual que con las sugerencias de tipo de
PEP 484
, estas son
completamente opcionales
y son de uso principal para las herramientas de verificación de tipos (y cualquier otra cosa que pueda crear en base a esta información).
Será provisional cuando se lance la versión estable de Python 3.6 para que se puedan agregar pequeños ajustes en el futuro.
Python 3.6 está a punto de ser lanzado. PEP 494 - El programa de lanzamiento de Python 3.6 menciona el final de diciembre, así que revisé What''s New in Python 3.6 para ver que mencionan las anotaciones variables :
PEP 484 introdujo el estándar para anotaciones de tipo de parámetros de función, también conocidos 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 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 tipados estáticamente, 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 atributo__annotations__
.
Entonces, por lo que leí, son parte de las sugerencias de tipo que provienen de Python 3.5, que se describen en Qué son las sugerencias de tipo en Python 3.5 .
Sigo al
captain: str
y
class Starship
Ejemplo de
class Starship
, pero no estoy seguro sobre el último: ¿Cómo explica
primes: List[int] = []
?
¿Está definiendo una lista vacía que solo permitirá enteros?
Todo entre
:
y
=
es una sugerencia de tipo, por lo que los
primes
se definen como
List[int]
, y se establecen inicialmente en una lista vacía (y
stats
es un diccionario vacío inicialmente, definido como
Dict[str, int]
).
List[int]
y
Dict[str, int]
no son parte de la siguiente sintaxis, sin embargo, estos ya se definieron en las sugerencias de escritura de Python 3.5 PEP.
La propuesta 3.6
PEP 526 -
Sintaxis para anotaciones variables
solo
define la sintaxis para adjuntar las mismas sugerencias a las variables;
antes solo podía adjuntar sugerencias de tipo a variables con comentarios (por ejemplo,
primes = [] # List[int]
).
Tanto
List
como
Dict
son tipos
genéricos
, lo que indica que tiene una lista o una asignación de diccionario con contenidos específicos (concretos).
Para
List
, solo hay un ''argumento'' (los elementos en la
[...]
sintaxis), el tipo de cada elemento en la lista.
Para
Dict
, el primer argumento es el tipo de clave y el segundo el tipo de valor.
Por
lo
tanto,
todos los
valores en la lista de
primes
son enteros, y
todos
los pares clave-valor en el diccionario de
stats
son pares
(str, int)
, asignando cadenas a enteros.
Vea la lista de
typing.List
y
typing.Dict
definiciones, la
sección sobre
Genéricos
, así como
PEP 483 -
La teoría de las sugerencias de tipo
.
Al igual que las sugerencias de tipo en las funciones, su uso es opcional y también se consideran
anotaciones
(siempre que haya un objeto para adjuntarlas, por lo tanto, globales en módulos y atributos en clases, pero no locales en funciones) que podría introspectar a través del atributo
__annotations__
.
Puede adjuntar información arbitraria a estas anotaciones, no está estrictamente limitado a escribir información de sugerencias.
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 introspectarlas y cómo declarar algo como un atributo de clase frente a un atributo de instancia, por ejemplo.