Wie kann ich den Funktionstyp in meinen Typhinweisen angeben?

135

Ich möchte Typhinweise in meinem aktuellen Python 3.5-Projekt verwenden. Meine Funktion sollte eine Funktion als Parameter erhalten.

Wie kann ich die Typfunktion in meinen Typhinweisen angeben?

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

Ich habe PEP 483 überprüft , konnte dort jedoch keinen Hinweis auf einen Funktionstyp finden.

Jon
quelle
20
Eine Funktion istCallable
Jonrsharpe
3
python.org/dev/peps/pep-0483/#fundamental-building-blocks , letzter Punkt vor "wir könnten hinzufügen".

Antworten:

171

Wie @jonrsharpe in einem Kommentar feststellte, kann dies folgendermaßen geschehen typing.Callable:

from typing import AnyStr, Callable

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

Das Problem ist, Callabledass für sich genommen übersetzt wird, Callable[..., Any]was bedeutet:

Ein Callable akzeptiert eine beliebige Anzahl von / type von Argumenten und gibt einen Wert von einem beliebigen Typ zurück. In den meisten Fällen ist dies nicht das, was Sie wollen, da Sie so gut wie jede Funktion übergeben können. Sie möchten, dass auch die Funktionsparameter und Rückgabetypen angedeutet werden.

Aus diesem Grund wurden viele typesin typingüberlastet, um Subskripte zu unterstützen, die diese zusätzlichen Typen kennzeichnen. Wenn Sie beispielsweise eine Funktion hatten sum, die zwei intSekunden benötigt und Folgendes zurückgibt int:

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

Ihre Anmerkung dazu wäre:

Callable[[int, int], int]

Das heißt, die Parameter werden im äußeren Abonnement mit dem Rückgabetyp als zweitem Element im äußeren Abonnement subskriptiert. Allgemein:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]
Dimitris Fasarakis Hilliard
quelle
25
Dieses typingZeug bringt die gesamte Python-Sprache um eine Stufe nach oben.
Javadba
1
@javadba - oh, ja, aber ich bin immer noch nicht sicher , auf welcher Wahl ... übrigens - was Callable[[Arg, Types, Here], ...]für *args, **kwargs, Keyword-only args und Positions nur args? Haben sie nicht darüber nachgedacht, Konventionen in den Typensignaturen für Callables aufzurufen? ;)
Tomasz Gandor
10

Ein weiterer interessanter Punkt ist, dass Sie die eingebaute Funktion verwenden können type(), um den Typ einer eingebauten Funktion abzurufen und diese zu verwenden. Also könntest du haben

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

Oder so etwas

Hallsville3
quelle
Ein Typhinweis kann beliebig sein, wurde jedoch nicht immer faul ausgewertet. Auch nimmt Ihre Funktion wirklich nur builtin_function_or_methodals my_function? Würde das nicht lambdafunktionieren? Eine benutzerdefinierte Funktion oder gebundene Methode?
Tomasz Gandor