Comment puis-je spécifier le type de fonction dans mes conseils de type?

137

Je souhaite utiliser des indices de type dans mon projet Python 3.5 actuel. Ma fonction devrait recevoir une fonction en paramètre.

Comment puis-je spécifier la fonction de type dans mes indices de type?

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

J'ai vérifié PEP 483 , mais je n'ai pas trouvé d'indice de type de fonction.

Jon
la source
21
Une fonction estCallable
jonrsharpe
3
python.org/dev/peps/pep-0483/#fundamental-building-blocks , dernier point avant "nous pourrions ajouter".

Réponses:

175

Comme @jonrsharpe l'a noté dans un commentaire, cela peut être fait avec typing.Callable:

from typing import AnyStr, Callable

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

Le problème est Callableque seul est traduit Callable[..., Any]ce qui signifie:

Un appelable prend n'importe quel nombre d' arguments / type et renvoie une valeur de n'importe quel type. Dans la plupart des cas, ce n'est pas ce que vous voulez car vous autoriserez à peu près n'importe quelle fonction à passer. Vous voulez que les paramètres de fonction et les types de retour soient également indiqués.

C'est pourquoi beaucoup de typesdans typingont été surchargés pour prendre en charge le sous-scripting qui dénote ces types supplémentaires. Donc si, par exemple, vous aviez une fonction sumqui prend deux ints et renvoie un int:

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

Votre annotation pour cela serait:

Callable[[int, int], int]

autrement dit, les paramètres sont sous-scriptés dans l'abonnement externe avec le type de retour comme deuxième élément dans l'abonnement externe. En général:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]
Dimitris Fasarakis Hilliard
la source
26
ce typingtruc déplace tout le langage python d'un cran.
javadba
1
@javadba - oh, oui, mais je ne suis toujours pas sûr sur lequel cadran ... Soit dit en passant - Qu'en est- il Callable[[Arg, Types, Here], ...]pour *args, **kwargsargs mots clés seulement et seulement args position? N'ont-ils pas pensé à appeler la convention dans les signatures de type pour les appelables? ;)
Tomasz Gandor
10

Un autre point intéressant à noter est que vous pouvez utiliser la fonction intégrée type()pour obtenir le type d'une fonction intégrée et l'utiliser. Alors tu pourrais avoir

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

Ou quelque chose de cette forme

Hallsville3
la source
Un indice de type peut être ce que vous souhaitez, mais il n'a pas toujours été évalué paresseusement. Aussi, votre fonction ne prend-elle vraiment que builtin_function_or_methodcomme my_function? Ne serait-ce pas un lambdatravail? Une fonction définie par l'utilisateur ou une méthode liée?
Tomasz Gandor