Inne odpowiedzi wykonały dobrą robotę wyjaśniając pisanie kaczek i prostą odpowiedź tzot :
Python nie ma zmiennych, podobnie jak inne języki, w których zmienne mają typ i wartość; ma nazwy wskazujące na obiekty, które znają ich typ.
Jednak jedna interesująca rzecz zmieniła się od 2010 roku (kiedy pytanie zostało zadane po raz pierwszy), a mianowicie implementacja PEP 3107 (zaimplementowana w Pythonie 3). Możesz teraz właściwie określić typ parametru i typ zwracanego typu funkcji:
def pick(l: list, index: int) -> int:
return l[index]
Widzimy tutaj, że pick
bierze 2 parametry, listę l
i liczbę całkowitą index
. Powinien także zwrócić liczbę całkowitą.
Tutaj sugeruje się, że l
jest to lista liczb całkowitych, które możemy zobaczyć bez większego wysiłku, ale w przypadku bardziej złożonych funkcji może być nieco mylące, co powinna zawierać lista. Chcemy również, aby domyślna wartość wynosiła index
0. Aby rozwiązać ten problem, możesz pick
zamiast tego napisać w następujący sposób:
def pick(l: "list of ints", index: int = 0) -> int:
return l[index]
Zauważ, że teraz wstawiamy ciąg jako typ l
, który jest składniowo dozwolony, ale nie nadaje się do parsowania programowego (do którego wrócimy później).
Ważne jest, aby pamiętać, że Python nie podniesie wartości, TypeError
jeśli przejdziesz do float index
, przyczyną tego jest jeden z głównych punktów filozofii projektowania Pythona: „Wszyscy zgadzamy się tutaj na dorosłych” , co oznacza, że oczekuje się bądź świadomy tego, co możesz przekazać do funkcji, a czego nie. Jeśli naprawdę chcesz napisać kod, który wyrzuca błędy TypeErrors, możesz użyć isinstance
funkcji, aby sprawdzić, czy przekazany argument jest poprawnego typu lub jego podklasy w następujący sposób:
def pick(l: list, index: int = 0) -> int:
if not isinstance(l, list):
raise TypeError
return l[index]
Więcej o tym, dlaczego tak rzadko powinieneś to robić, a o tym, co powinieneś zrobić, omówiono w następnej sekcji i w komentarzach.
PEP 3107 nie tylko poprawia czytelność kodu, ale ma także kilka pasujących przypadków użycia, o których możesz przeczytać tutaj .
Adnotacja typu zyskała dużo większą uwagę w Pythonie 3.5 dzięki wprowadzeniu PEP 484, który wprowadza standardowy moduł do wskazówek typu.
Te wskazówki dotyczące typów pochodzą od mypy sprawdzania typu ( GitHub ), która jest teraz zgodna z PEP 484 .
Z modułem do pisania dołączony jest dość obszerny zbiór wskazówek dotyczących typów, w tym:
List
, Tuple
, Set
, Map
- do list
, tuple
, set
i map
odpowiednio.
Iterable
- przydatne dla generatorów.
Any
- kiedy może być cokolwiek.
Union
- kiedy może to być cokolwiek w ramach określonego zestawu typów, w przeciwieństwie do Any
.
Optional
- kiedy może to być Brak. Stenografia dla Union[T, None]
.
TypeVar
- stosowany z lekami generycznymi.
Callable
- używany głównie do funkcji, ale może być wykorzystany do innych wywołań.
Są to najczęstsze wskazówki dotyczące typów. Pełną listę można znaleźć w dokumentacji modułu do pisania .
Oto stary przykład wykorzystujący metody adnotacji wprowadzone w module pisania:
from typing import List
def pick(l: List[int], index: int) -> int:
return l[index]
Jedną z potężnych funkcji jest Callable
możliwość wpisywania metod adnotacji, które przyjmują funkcję jako argument. Na przykład:
from typing import Callable, Any, Iterable
def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
"""An immediate version of map, don't pass it any infinite iterables!"""
return list(map(f, l))
Powyższy przykład może stać się bardziej precyzyjny z użyciem TypeVar
zamiast Any
, ale zostało to pozostawione jako ćwiczenie dla czytelnika, ponieważ uważam, że już wypełniłem moją odpowiedź zbyt dużą ilością informacji o cudownych nowych funkcjach włączonych przez podpowiedzi typu.
Wcześniej, gdy udokumentowano jeden kod Pythona, na przykład Sphinx, niektóre z powyższych funkcji można było uzyskać pisząc dokumenty w formacie takim jak ten:
def pick(l, index):
"""
:param l: list of integers
:type l: list
:param index: index at which to pick an integer from *l*
:type index: int
:returns: integer at *index* in *l*
:rtype: int
"""
return l[index]
Jak widać, wymaga to kilku dodatkowych wierszy (dokładna liczba zależy od tego, jak wyraźny chcesz być i jak formatujesz dokumenty). Ale teraz powinno być dla ciebie jasne, w jaki sposób PEP 3107 stanowi alternatywę, która jest na wiele (wszystkich?) Sposobów lepsza. Jest to szczególnie prawdziwe w połączeniu z PEP 484, który, jak widzieliśmy, zapewnia standardowy moduł, który definiuje składnię dla tego typu wskazówek / adnotacji, które mogą być używane w taki sposób, że są jednoznaczne i precyzyjne, a jednocześnie elastyczne, tworząc potężna kombinacja.
Moim osobistym zdaniem jest to jedna z największych funkcji Pythona w historii. Nie mogę się doczekać, aż ludzie zaczną wykorzystywać jego moc. Przepraszam za długą odpowiedź, ale tak się dzieje, kiedy się ekscytuję.
Przykład kodu Pythona, który intensywnie korzysta z podpowiedzi typu, można znaleźć tutaj .