Una de las características más comentadas en Python 3.5 son las sugerencias de tipo .
Se menciona un ejemplo de sugerencias de tipo en este artículo y en este, al tiempo que se menciona el uso responsable de sugerencias de tipo. ¿Alguien puede explicar más sobre ellos y cuándo deberían usarse y cuándo no?
python
python-3.x
python-3.5
type-hinting
Vaulstein
fuente
fuente
Respuestas:
Sugeriría leer PEP 483 y PEP 484 y ver esta presentación de Guido sobre Sugerencias de tipo.
En pocas palabras : la sugerencia de tipo es literalmente lo que significan las palabras, usted insinúa el tipo de objeto (s) que está utilizando .
Debido a la naturaleza dinámica de Python, inferir o verificar el tipo de un objeto que se está utilizando es especialmente difícil. Este hecho dificulta que los desarrolladores comprendan qué está sucediendo exactamente en el código que no han escrito y, lo que es más importante, las herramientas de verificación de tipos que se encuentran en muchos IDE [PyCharm, PyDev vienen a mi mente] que están limitados debido al hecho de que no tienen ningún indicador de qué tipo son los objetos. Como resultado, recurren a tratar de inferir el tipo con (como se mencionó en la presentación) alrededor del 50% de tasa de éxito.
Para tomar dos diapositivas importantes de la presentación Sugerencia de tipo:
¿Por qué escribir sugerencias?
TypeErrors
..
y teniendo métodos / atributos emergentes que no están definidos para un objeto.¿Por qué usar Checkers de tipo estático?
Como nota final para esta pequeña introducción : esta es una característica opcional y, por lo que entiendo, se ha introducido para obtener algunos de los beneficios de la escritura estática.
Por lo general , no necesita preocuparse por eso y definitivamente no necesita usarlo (especialmente en los casos en que usa Python como un lenguaje de script auxiliar). Debería ser útil al desarrollar grandes proyectos, ya que ofrece la robustez, el control y las capacidades de depuración adicionales que tanto se necesitan .
Escriba Sugerencia con mypy :
Para que esta respuesta sea más completa, creo que una pequeña demostración sería adecuada. Usaré
mypy
la biblioteca que inspiró las Sugerencias de tipo tal como se presentan en el PEP. Esto está escrito principalmente para cualquiera que se encuentre con esta pregunta y se pregunte por dónde comenzar.Antes de hacerlo, permítanme reiterar lo siguiente: PEP 484 no impone nada; simplemente establece una dirección para las anotaciones de funciones y propone pautas sobre cómo se puede / se debe realizar la verificación de tipo. Puede anotar sus funciones e insinuar tantas cosas como desee; sus scripts se seguirán ejecutando independientemente de la presencia de anotaciones porque Python en sí no las usa.
De todos modos, como se señala en la PEP, los tipos de sugerencias generalmente deben tomar tres formas:
# type: type
Comentarios especiales que complementan las dos primeras formas. (Consulte: ¿Qué son las anotaciones variables en Python 3.6? Para una actualización de Python 3.6 para# type: type
comentarios)Además, querrá usar sugerencias de tipo junto con el nuevo
typing
módulo introducido enPy3.5
. En él, se definen muchos ABC (clases base abstractas) (adicionales) junto con funciones auxiliares y decoradores para su uso en la comprobación estática. La mayoríaABCs
encollections.abc
están incluidas, pero en unaGeneric
forma a fin de permitir la suscripción (mediante la definición de un__getitem__()
método).Para cualquier persona interesada en una explicación más detallada de estos, el
mypy documentation
está escrito muy bien y tiene muchos ejemplos de código que demuestran / describen la funcionalidad de su verificador; definitivamente vale la pena leerlo.Anotaciones de funciones y comentarios especiales:
Primero, es interesante observar algunos de los comportamientos que podemos obtener al usar comentarios especiales. Se
# type: type
pueden agregar comentarios especiales durante las asignaciones de variables para indicar el tipo de un objeto si no se puede inferir directamente uno. Las tareas simples generalmente se infieren fácilmente, pero otras, como las listas (con respecto a su contenido), no pueden.Nota: Si queremos usar cualquier derivada de
Containers
y necesitamos especificar los contenidos para ese contenedor, debemos usar los tipos genéricos deltyping
módulo. Estos soportan la indexación.Si agregamos estos comandos a un archivo y los ejecutamos con nuestro intérprete, todo funciona bien y
print(a)
solo imprime el contenido de la listaa
. Los# type
comentarios han sido descartados, tratados como comentarios simples que no tienen un significado semántico adicional .Al ejecutar esto con
mypy
, por otro lado, obtenemos la siguiente respuesta:Indicando que una lista de
str
objetos no puede contener unint
, que, estáticamente hablando, es sólido. Esto se puede solucionar ya sea respetando el tipo de objetosa
y solo agregándolosstr
o cambiando el tipo de contenido dea
para indicar que cualquier valor es aceptable (realizado de forma intuitiva conList[Any]
después de queAny
se ha importadotyping
).Las anotaciones de función se agregan en el formulario
param_name : type
después de cada parámetro en su firma de función y se especifica un tipo de retorno utilizando la-> type
notación antes de la función de finalización de dos puntos; todas las anotaciones se almacenan en el__annotations__
atributo para esa función en un práctico formulario de diccionario. Usando un ejemplo trivial (que no requiere tipos adicionales deltyping
módulo):El
annotated.__annotations__
atributo ahora tiene los siguientes valores:Si somos un novato completo, o estamos familiarizados con los
Py2.7
conceptos y, en consecuencia, no somos conscientes delTypeError
acecho en la comparación deannotated
, podemos realizar otra comprobación estática, detectar el error y ahorrarnos algunos problemas:Entre otras cosas, llamar a la función con argumentos no válidos también quedará atrapado:
Estos pueden extenderse básicamente a cualquier caso de uso y los errores detectados se extienden más allá de las llamadas y operaciones básicas. Los tipos que puede verificar son realmente flexibles y simplemente he dado un pequeño adelanto de su potencial. Una mirada en el
typing
módulo, los PEP o losmypy
documentos le dará una idea más completa de las capacidades ofrecidas.Archivos Stub:
Los archivos de código auxiliar se pueden usar en dos casos diferentes no mutuamente excluyentes:
Los archivos de código auxiliar (con una extensión de
.pyi
) son una interfaz anotada del módulo que está creando / desea utilizar. Contienen las firmas de las funciones que desea verificar con el cuerpo de las funciones descartadas. Para tener una idea de esto, dado un conjunto de tres funciones aleatorias en un módulo llamadorandfunc.py
:Podemos crear un archivo apéndice
randfunc.pyi
, en el que podemos colocar algunas restricciones si lo deseamos. La desventaja es que alguien que vea la fuente sin el código auxiliar realmente no recibirá esa ayuda de anotación cuando intente entender qué se supone que se debe pasar a dónde.De todos modos, la estructura de un archivo apéndice es bastante simplista: agregue todas las definiciones de funciones con cuerpos vacíos (
pass
rellenos) y proporcione las anotaciones basadas en sus requisitos. Aquí, supongamos que solo queremos trabajar conint
tipos para nuestros Contenedores.La
combine
función da una indicación de por qué es posible que desee utilizar anotaciones en un archivo diferente, algunas veces abarrotan el código y reducen la legibilidad (gran no-no para Python). Por supuesto, podría usar alias de tipo, pero eso a veces confunde más de lo que ayuda (así que úselos sabiamente).Esto debería familiarizarlo con los conceptos básicos de Type Hints en Python. A pesar de que el verificador de tipo utilizado ha sido
mypy
gradual, debería comenzar a ver más ventanas emergentes, algunas internamente en IDEs ( PyCharm ) y otras como módulos estándar de Python. Intentaré agregar verificadores adicionales / paquetes relacionados en la siguiente lista cuando y si los encuentro (o si se sugiere).Damas que conozco :
Paquetes / proyectos relacionados :
El
typeshed
proyecto es en realidad uno de los mejores lugares en los que puede mirar para ver cómo se pueden usar las sugerencias de tipo en un proyecto propio. Tomemos como ejemplo los__init__
usuarios de laCounter
clase en el.pyi
archivo correspondiente :Donde
_T = TypeVar('_T')
se usa para definir clases genéricas . Para laCounter
clase podemos ver que no puede tomar argumentos en su inicializador, obtener un soloMapping
de cualquier tipo a unoint
o tomar unoIterable
de cualquier tipo.Aviso : Una cosa que olvidé mencionar es que el
typing
módulo se ha introducido de forma provisional . De PEP 411 :Así que toma las cosas aquí con una pizca de sal; Dudo que se elimine o altere de manera significativa, pero nunca se puede saber.
** Otro tema completo pero válido en el ámbito de las sugerencias de tipo
PEP 526
: La sintaxis para anotaciones de variables es un esfuerzo para reemplazar los# type
comentarios mediante la introducción de una nueva sintaxis que permite a los usuarios anotar el tipo de variables envarname: type
declaraciones simples .Consulte ¿Qué son las anotaciones variables en Python 3.6? , como se mencionó anteriormente, para una pequeña introducción sobre estos.
fuente
Agregando a la elaborada respuesta de Jim:
Verifique el
typing
módulo : este módulo admite sugerencias de tipo según lo especificado por PEP 484 .Por ejemplo, la siguiente función toma y devuelve valores de tipo
str
y se anota de la siguiente manera:El
typing
módulo también admite:fuente
El recientemente lanzado PyCharm 5 admite sugerencias de tipo. En su publicación de blog al respecto (consulte Sugerencias de tipo Python 3.5 en PyCharm 5 ) ofrecen una excelente explicación de qué sugerencias de tipo son y qué no, junto con varios ejemplos e ilustraciones sobre cómo usarlas en su código.
Además, es compatible con Python 2.7, como se explica en este comentario :
fuente
La sugerencia de tipo es una adición reciente a un lenguaje dinámico donde durante décadas la gente juró convenciones de nombres tan simples como húngaro (etiqueta de objeto con la primera letra b = boolian, c = carácter, d = diccionario, i = entero, l = lista, n = numérico , s = string, t = tuple) no eran necesarios, demasiado engorroso, pero ahora he decidido que, oh, espera ... es demasiado problema usar el lenguaje (type ()) para reconocer objetos, y nuestros IDEs elegantes necesitan ayuda para hacer algo que sea complicado, y que los valores de objeto asignados dinámicamente los vuelven completamente inútiles de todos modos, mientras que una simple convención de nomenclatura podría haber resuelto todo, para cualquier desarrollador, de un simple vistazo.
fuente
Las sugerencias de tipo son para mantenimiento y no son interpretadas por Python. En el siguiente código, la línea
def add(self, ic:int)
no produce un error hasta la siguientereturn...
línea:fuente