Jak mogę określić typ funkcji w moich wskazówkach dotyczących typu?


138

Chcę użyć wskazówek dotyczących typów w moim bieżącym projekcie Python 3.5. Moja funkcja powinna otrzymać funkcję jako parametr.

Jak mogę określić funkcję typu w moich wskazówkach dotyczących typu?

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

Sprawdziłem PEP 483 , ale nie mogłem tam znaleźć podpowiedzi typu funkcji.


21
Funkcją jestCallable
jonrsharpe

3
python.org/dev/peps/pep-0483/#fundamental-building-blocks , ostatni punktor przed „możemy dodać”.

Odpowiedzi:


176

Jak zauważył @jonrsharpe w komentarzu, można to zrobić za pomocą typing.Callable:

from typing import AnyStr, Callable

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

Problem w tym, Callableże sam jest tłumaczony na Callable[..., Any]co oznacza:

Funkcja wywoływana przyjmuje dowolną liczbę argumentów / typ i zwraca wartość dowolnego typu. W większości przypadków nie jest to to, czego chcesz, ponieważ pozwolisz na przekazanie prawie każdej funkcji. Chcesz, aby parametry funkcji i typy zwracane były również wskazywane.

Dlatego wiele typesz typingnich zostało przeciążonych, aby obsługiwać podskrypty, które oznaczają te dodatkowe typy. Więc jeśli na przykład masz funkcję, sumktóra zajmuje dwie intsekundy i zwraca int:

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

Twoja adnotacja będzie wyglądać tak:

Callable[[int, int], int]

oznacza to, że parametry są subskryptowane w subskrypcji zewnętrznej, a typ zwracany jest drugim elementem w subskrypcji zewnętrznej. Ogólnie:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]

26
ta typingrzecz przenosi cały język Pythona o jeden stopień wyżej.
javadba

1
@javadba - Och, tak, ale ja nadal nie jestem pewien która na tarczy ... Przy okazji - co Callable[[Arg, Types, Here], ...]za *args, **kwargs, słowa kluczowe tylko args i pozycyjnych tylko args? Czy nie myśleli o wywołaniu konwencji w podpisach czcionek dla wywołań? ;)
Tomasz Gandor

11

Inną interesującą kwestią, na którą należy zwrócić uwagę, jest to, że możesz użyć funkcji wbudowanej, type()aby uzyskać typ funkcji wbudowanej i użyć jej. Więc mogłeś

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

Albo coś w tej formie


Wskazówka dotycząca typu może być dowolna, ale nie zawsze była oceniana leniwie. Poza tym, czy twoja funkcja naprawdę przyjmuje tylko builtin_function_or_methodjako my_function? Nie byłoby lambdapracy? Funkcja zdefiniowana przez użytkownika lub metoda powiązana?
Tomasz Gandor

bardzo sprytny sposób, przynajmniej do rozwiązywania problemów lub burzy mózgów
oldpride
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.