Adnotacja typu powrotu void w języku Python

118

W Pythonie 3.x często używa się adnotacji typu zwracanego funkcji, takich jak:

def foo() -> str:
    return "bar"

Jaka jest prawidłowa adnotacja dla typu „void”?

Rozważam 3 opcje:

  1. def foo() -> None:
    • nie logiczne IMO, ponieważ Nonenie jest typem,
  2. def foo() -> type(None):
    • używając najlepszej znanej mi składni do uzyskania NoneType,
  3. def foo():
    • pomiń jawne informacje o zwracanym typie.

Opcja 2. wydaje mi się najbardziej logiczna, ale widziałem już kilka przykładów 1.

Tregoreg
źródło
12
FWIW, Python nie ma funkcji z voidtypem zwracanym. Dowolna funkcja (lub gałąź funkcji) bez jawności returnzwróci None. Zakładam, że OP rozumie, że ten komentarz jest głównie dla przyszłych czytelników ...
PM 2Ring
Cóż, to pytanie nie jest tak popularne, jak „dlaczego moja funkcja zwraca wartość None w Pythonie?” (Zmyśliłem to pytanie), więc prawdopodobnie większość czytelników zna już domyślne zachowanie. W odpowiedzi rozwiązany jest dylemat 1 vs 2. Ale co z 3? W przypadku „procedur” właściwie wolałbym opcję 3, bez zbędnego bałaganu (w końcu ta funkcja nic nie zwraca).
Tomasz Gandor
@TomaszGandor Zgadzam się. Gdy funkcja lub metoda nie zawiera instrukcji powrotu, nie ma potrzeby określania jej typu zwracanego.
Jeyekomon,

Odpowiedzi:

128

To pochodzi prosto z dokumentacji PEP 484 - Wskazówki dotyczące typów :

W przypadku użycia w wskazówce dotyczącej typu wyrażenie Nonejest traktowane jako równoważne type(None).

Jak widać, większość przykładów używa Nonejako typu zwracanego.

AKS
źródło
22
Aby wyjaśnić, wybierz opcję 1 powyżej.
Adam Nelson
13
@asmaier zgodnie z tym pytaniem , które przytacza PEP 484 - wskazówki typu NoReturn typ jest używany „... do funkcji adnotacje, że nigdy nie wróci normalnie Na przykład, funkcja, która bezwarunkowo podnosi wyjątek ...”
Rodrigo Laguna
40

TLDR: idiomatyczny odpowiednik voidadnotacji typu zwracanego to -> None.

def foo() -> None:
    ...

Ten odpowiada, że funkcja bez returnlub tylko gołe returnma wartość None.

def void_func():  # unannotated void function
    pass

print(void())  # None

Pominięcie zwracanego typu nie oznacza, że ​​nie ma zwracanej wartości. Zgodnie z PEP 484 :

W przypadku funkcji zaznaczonej domyślną adnotacją dla argumentów i dla typu zwracanego jest Any.

Oznacza to, że wartość jest uważana za wpisaną dynamicznie i statycznie obsługuje każdą operację . To jest praktycznie przeciwne znaczenie void.


Podpowiedzi do typów w Pythonie nie wymagają ściśle określonych typów. Na przykład, adnotacje mogą używać ciągów nazw typu: Union[str, int], Union[str, 'int'], 'Union[str, int]'i różne warianty są równoważne.

Podobnie Noneuważa się , że adnotacja typu oznacza „jest z NoneType”. Można to wykorzystać nie tylko w przypadku typów zwracanych, chociaż zobaczysz to najczęściej:

bar : None

def foo(baz: None) -> None:
    return None

Dotyczy to również typów ogólnych. Na przykład można użyć Nonein, Generator[int, None, None]aby wskazać, że generator nie przyjmuje ani nie zwraca wartości.


Mimo że PEP 484 sugeruje, że Noneto oznacza type(None), nie należy jawnie używać tej drugiej formy. Specyfikacja podpowiedzi typu nie obejmuje żadnej formy type(...). Jest to technicznie wyrażenie środowiska uruchomieniowego, a jego obsługa zależy wyłącznie od sprawdzania typów. mypyProjekt rozważa usunięcie wsparcia dla type(None)i usunąć go z 484, jak również.

A może powinniśmy zaktualizować PEP 484, aby nie sugerował, że type(None)jest ważny jako typ i Nonejest jedyną poprawną pisownią? Powinien być jeden - a najlepiej tylko jeden - oczywisty sposób na zrobienie tego itp.

--- JukkaL, 18 maja 2018 r

MisterMiyagi
źródło
4
Ogromne okrzyki za wyjaśnienie, dlaczego trzecia opcja w ogóle nie jest funkcją void.
никта