¿Cómo puedo especificar el tipo de función en mis sugerencias de tipo?

137

Quiero usar sugerencias de tipo en mi proyecto actual de Python 3.5. Mi función debería recibir una función como parámetro.

¿Cómo puedo especificar la función de tipo en mis sugerencias de tipo?

import typing

def my_function(name:typing.AnyStr, func: typing.Function) -> None:
    # However, typing.Function does not exist.
    # How can I specify the type function for the parameter `func`?

    # do some processing
    pass

Revisé PEP 483 , pero no pude encontrar una pista de tipo de función allí.

Jon
fuente
21
Una función esCallable
jonrsharpe
3
python.org/dev/peps/pep-0483/#fundamental-building-blocks , último punto antes de "podríamos agregar".

Respuestas:

174

Como @jonrsharpe señaló en un comentario, esto se puede hacer con typing.Callable:

from typing import AnyStr, Callable

def my_function(name: AnyStr, func: Callable) -> None:

El problema es que, Callablepor sí solo, se traduce a lo Callable[..., Any]que significa:

Un invocable toma cualquier número de argumentos / tipo y devuelve un valor de cualquier tipo. En la mayoría de los casos, esto no es lo que desea, ya que permitirá que se pase casi cualquier función. Desea que se insinúen también los parámetros de función y los tipos de retorno.

Es por eso que muchos typesde typinghaber sido sobrecargado para el apoyo sub-secuencias de comandos que denota estos tipos adicionales. Entonces, si, por ejemplo, tuvo una función sumque toma dos intsy devuelve un int:

def sum(a: int, b: int) -> int: return a+b

Su anotación para ello sería:

Callable[[int, int], int]

es decir, los parámetros se subescriben en la suscripción externa con el tipo de retorno como el segundo elemento en la suscripción externa. En general:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]
Dimitris Fasarakis Hilliard
fuente
26
Esto typingmueve el lenguaje completo de Python a un nivel superior.
javadba
1
@javadba - Oh, sí, pero todavía no estoy seguro sobre el cual marcación ... Por cierto - ¿qué hay Callable[[Arg, Types, Here], ...]para *args, **kwargs, args palabra clave única y sólo argumentos posicionales? ¿No han pensado en llamar a la convención en las firmas de tipo para las llamadas? ;)
Tomasz Gandor
10

Otro punto interesante a tener en cuenta es que puede usar la función integrada type()para obtener el tipo de función integrada y usarla. Entonces podrías tener

def f(my_function: type(abs)) -> int:
    return my_function(100)

O algo de esa forma

Hallsville3
fuente
Una sugerencia de tipo puede ser lo que desee, pero no siempre se han evaluado de forma diferida. Además, ¿su función realmente solo toma builtin_function_or_methodcomo my_function? ¿No sería un lambdatrabajo? ¿Una función definida por el usuario o un método vinculado?
Tomasz Gandor