Recientemente noté algo interesante al mirar la especificación de gramática de Python 3.3 :
funcdef: 'def' NAME parameters ['->' test] ':' suite
El bloque de 'flecha' opcional estaba ausente en Python 2 y no pude encontrar ninguna información sobre su significado en Python 3. Resulta que esto es Python correcto y el intérprete lo acepta:
def f(x) -> 123: return x
Pensé que esto podría ser algún tipo de sintaxis de condición previa, pero:
x
aquí, ya que aún no está definido,2 < 1
), no afecta el comportamiento de la función.¿Alguien que esté familiarizado con este estilo de sintaxis podría explicarlo?
Como han indicado otras respuestas, el símbolo ->
se usa como parte de las anotaciones de funciones. Sin embargo, en versiones más recientes de Python >= 3.5
, tiene un significado definido .
PEP 3107 -- Las anotaciones de funciones describen la especificación, definiendo los cambios gramaticales, la existencia de func.__annotations__
de funciones en las que se almacenan y el hecho de que su caso de uso aún está abierto.
Sin embargo, en Python 3.5
, PEP 484 -- Type Hints le da un solo significado a esto: ->
se usa para indicar el tipo que devuelve la función. También parece que esto se aplicará en versiones futuras, como se describe en ¿Qué pasa con los usos existentes de las anotaciones ?
El esquema más rápido concebible introduciría la desaprobación silenciosa de las anotaciones que no son sugerencias de tipo en 3.6, la desaprobación total en 3.7 y declararía las sugerencias de tipo como el único uso permitido de anotaciones en Python 3.8.
(Énfasis mío)
Esto no se ha implementado en realidad a partir de 3.6
, por lo que puedo decir, por lo que podría pasar a versiones futuras.
De acuerdo con esto, el ejemplo que ha proporcionado:
def f(x) -> 123: return x
estará prohibido en el futuro (y en las versiones actuales será confuso), debería cambiarse a:
def f(x) -> int: return x
para que describa efectivamente esa función f
devuelve un objeto de tipo int
.
Python no usa las anotaciones de ninguna manera, prácticamente las completa y las ignora. Depende de las bibliotecas de terceros trabajar con ellos.
Es una anotación de función .
Con más detalle, Python 2.x tiene cadenas de documentos, que le permiten adjuntar una cadena de metadatos a varios tipos de objetos. Esto es increíblemente útil, por lo que Python 3 amplía la función al permitirle adjuntar metadatos a funciones que describen sus parámetros y valores devueltos.
No hay un caso de uso preconcebido, pero el PEP sugiere varios. Uno muy útil es permitirle anotar parámetros con sus tipos esperados; entonces sería fácil escribir un decorador que verifique las anotaciones o fuerce los argumentos al tipo correcto. Otra es permitir la documentación específica de parámetros en lugar de codificarla en la cadena de documentación.
Estas son anotaciones de funciones cubiertas en PEP 3107 . Específicamente, el ->
marca la anotación de la función de retorno.
Ejemplos:
def kinetic_energy(m:'in KG', v:'in M/S')->'Joules': return 1/2*m*v**2 >>> kinetic_energy.__annotations__ {'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}
Las anotaciones son diccionarios, así que puedes hacer esto:
>>> '{:,} {}'.format(kinetic_energy(12,30), kinetic_energy.__annotations__['return']) '5,400.0 Joules'
También puede tener una estructura de datos de Python en lugar de solo una cadena:
rd={'type':float,'units':'Joules', 'docstring':'Given mass and velocity returns kinetic energy in Joules'} def f()->rd: pass >>> f.__annotations__['return']['type'] <class 'float'> >>> f.__annotations__['return']['units'] 'Joules' >>> f.__annotations__['return']['docstring'] 'Given mass and velocity returns kinetic energy in Joules'
O bien, puede usar atributos de función para validar los valores llamados:
def validate(func, locals): for var, test in func.__annotations__.items(): value = locals[var] try: pr=test.__name__+': '+test.__docstring__ except AttributeError: pr=test.__name__ msg = '{}=={}; Test: {}'.format(var, value, pr) assert test(value), msg def between(lo, hi): def _between(x): return lo <= x <= hi _between.__docstring__='must be between {} and {}'.format(lo,hi) return _between def f(x: between(3,10), y:lambda _y: isinstance(_y,int)): validate(f, locals()) print(x,y)
Huellas dactilares
>>> f(2,2) AssertionError: x==2; Test: _between: must be between 3 and 10 >>> f(3,2.1) AssertionError: y==2.1; Test: <lambda>
Esto significa el tipo de resultado que devuelve la función, pero puede ser None
.
Está muy extendido en las bibliotecas modernas orientadas a Python 3.x.
Por ejemplo, existe en el código de la biblioteca pandas-profiling en muchos lugares, por ejemplo:
def get_description(self) -> dict: def get_rejected_variables(self, threshold: float = 0.9) -> list: def to_file(self, output_file: Path or str, silent: bool = True) -> None: """Write the report to a file.
def function(arg)->123:
Es simplemente un tipo de retorno, entero en este caso no importa qué número escriba.
como Java :
public int function(int args){...}
Pero para Python (como dijo Jim Fasarakis Hilliard ) el tipo de retorno es solo una pista , por lo que sugiere el retorno pero permite de todos modos devolver otro tipo como una cadena.
En el siguiente código:
def f(x) -> int: return int(x)
-> int
solo dice que f()
devuelve un número entero (pero no obliga a la función a devolver un número entero). Se llama anotación de devolución y se puede acceder a ella como f.__annotations__['return']
.
Python también admite anotaciones de parámetros:
def f(x: float) -> int: return int(x)
: float
le dice a las personas que leen el programa (y algunas bibliotecas/programas de terceros, por ejemplo, pylint) que x
debería ser un float
. Se accede como f.__annotations__['x']
, y no tiene ningún significado por sí mismo. Consulte la documentación para obtener más información:
https://docs.python.org/3/reference/compound_stmts.html#function-definitions https://www.python.org/dev/peps/pep-3107/
solo le dice al usuario lo que espera esperar o devolver el valor
funcname.__annotations__
imprimirá los detalles
me gusta
def function(name:str ,age:int) -> "printing the personal details ": print(f"name is {name} age is {age}") function("test",20) print(function.__annotations__)
La salida
name is test age is 20 {'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}
incluso cuando devuelve los valores, no muestra nada.
-> se introduce en python3.
En palabras más simples, el contenido después de -> denota el tipo de retorno de la función. El tipo de retorno es opcional.
def f(x) -> 123: return x
Mi resumen:
Simplemente ->
se introduce para que los desarrolladores especifiquen opcionalmente el tipo de retorno de la función. Consulte la propuesta de mejora de Python 3107
Esta es una indicación de cómo pueden desarrollarse las cosas en el futuro a medida que Python se adopte ampliamente, una indicación hacia una tipificación fuerte, esta es mi observación personal.
También puede especificar tipos para argumentos. Especificar el tipo de devolución de las funciones y los argumentos ayudará a reducir los errores lógicos y mejorar las mejoras del código.
Puede tener expresiones como tipo de retorno (tanto a nivel de función como de parámetro) y se puede acceder al resultado de las expresiones a través del atributo 'retorno' del objeto de anotaciones . las anotaciones estarán vacías para la expresión/valor devuelto para las funciones en línea lambda.
def f(x) -> str: return x+4 print(f(45))
Dará el resultado : 49 .
O, en otras palabras, '-> str' NO tiene efecto en el tipo de retorno:
print(f(45).__class__) <class 'int'>