Wkrótce zostanie wydany Python 3.6. PEP 494 - Harmonogram wydania Pythona 3.6 wspomina o końcu grudnia, więc przejrzałem Co nowego w Pythonie 3.6, aby zobaczyć, jak wspominają o adnotacjach zmiennych :
PEP 484 wprowadził standard dla adnotacji typu parametrów funkcji, czyli podpowiedzi typu. Ten PEP dodaje składnię do Pythona w celu dodawania adnotacji do typów zmiennych, w tym zmiennych klas i zmiennych instancji:
primes: List[int] = [] captain: str # Note: no initial value! class Starship: stats: Dict[str, int] = {}
Podobnie jak w przypadku adnotacji funkcji, interpreter Pythona nie przypisuje żadnego szczególnego znaczenia adnotacjom zmiennych, a jedynie przechowuje je w specjalnym atrybucie
__annotations__
klasy lub modułu. W przeciwieństwie do deklaracji zmiennych w językach z typami statycznymi, celem składni adnotacji jest zapewnienie łatwego sposobu określania metadanych typu strukturalnego dla narzędzi i bibliotek innych firm za pośrednictwem abstrakcyjnego drzewa składni i__annotations__
atrybutu.
Tak więc z tego, co przeczytałem, są one częścią wskazówek dotyczących typów pochodzących z Pythona 3.5, opisanych w Co to są wskazówki dotyczące typów w Pythonie 3.5 .
Podążam za przykładem captain: str
i class Starship
, ale nie jestem pewien co do ostatniego: Jak to primes: List[int] = []
wyjaśnić? Czy definiuje pustą listę, która będzie zezwalać tylko na liczby całkowite?
źródło
primes: List[int] = []
jest po prostu pustą listą jakoprimes = []
. Różnica polega na tym, że twierdzisz, żeprimes
ma zawierać tylkoint
s, a aplikacje innych firm mogą wpisać sprawdź swój program, aby zweryfikować to oświadczenie, ale kiedy uruchamiasz kod w dowolnym interpreterze Pythona, jest to to samo, co pisanieprimes = []
, a zatemprimes: List[int] = []; primes.append("string")
nadal ważny.Odpowiedzi:
Wszystko pomiędzy
:
a=
jest wskazówką dotyczącą typu, więcprimes
jest rzeczywiście zdefiniowane jakoList[int]
i początkowo ustawione na pustą listę (istats
początkowo jest pustym słownikiem, zdefiniowanym jakoDict[str, int]
).List[int]
iDict[str, int]
nie są częścią kolejnej składni, jednak zostały one już zdefiniowane we wskazówkach dotyczących pisania w PEP w Pythonie 3.5. 3.6 PEP 526 - Składnia Zmienne adnotacji wniosku tylko definiuje składnię, aby dołączyć te same wskazówki do zmiennych; wcześniej można było tylko dołączać wskazówki dotyczące typów do zmiennych z komentarzami (npprimes = [] # List[int]
.).Oba typy
List
iDict
są typami ogólnymi , co oznacza, że masz mapowanie listy lub słownika z określoną (konkretną) zawartością.Ponieważ
List
istnieje tylko jeden „argument” (elementy[...]
składni), typ każdego elementu na liście. BoDict
pierwszy argument to typ klucza, a drugi typ wartości. Zatem wszystkie wartości naprimes
liście są liczbami całkowitymi, a wszystkie pary klucz-wartość wstats
słowniku są(str, int)
parami, odwzorowującymi łańcuchy na liczby całkowite.Zobacz definicje
typing.List
ityping.Dict
, rozdział dotyczący typów ogólnych , a także PEP 483 - Teoria wskazówek dotyczących typów .Podobnie jak w przypadku wskazówek dotyczących typów funkcji, ich użycie jest opcjonalne i są również uważane za adnotacje (pod warunkiem, że istnieje obiekt, do którego można je dołączyć, czyli wartości globalne w modułach i atrybuty klas, ale nie lokalne w funkcjach), które można przeszukiwać za pomocą
__annotations__
atrybutu. Możesz dołączać dowolne informacje do tych adnotacji, nie jesteś ściśle ograniczony do wpisywania wskazówek.Możesz przeczytać całą propozycję ; zawiera dodatkowe funkcje wykraczające poza nową składnię; określa, kiedy takie adnotacje są oceniane, jak je introspekować i jak na przykład zadeklarować coś jako atrybut klasy w porównaniu z atrybutem instancji.
źródło
obj.__annotations__
atrybutu)?Adnotacje zmiennych to tylko kolejny krok po
# type
komentarzach, tak jak zostały zdefiniowane wPEP 484
; uzasadnienie tej zmiany podkreślono w odpowiedniej sekcji PEP 526 .Więc zamiast podpowiadać typ za pomocą:
primes = [] # type: List[int]
Wprowadzono nową składnię, aby umożliwić bezpośrednie przypisanie typu adnotacji do formularza:
primes: List[int] = []
który, jak zauważył @Martijn, oznacza listę liczb całkowitych przy użyciu typów dostępnych w programie
typing
i inicjalizując ją jako pustą listę.Pierwszą wprowadzoną zmianą była nowa składnia, która umożliwia
:
przypisywanie do nazwy typu, samodzielnego po znaku lub opcjonalnie adnotacji z jednoczesnym przypisaniem do niej wartości:annotated_assignment_stmt ::= augtarget ":" expression ["=" expression]
A więc przykład o którym mowa:
primes: List[int] = [ ] # ^ ^ ^ # augtarget | | # expression | # expression (optionally initialize to empty list)
Dodatkowe zmiany zostały również wprowadzone wraz z nową składnią; moduły i klasy mają teraz
__annotations__
atrybut (tak jak funkcje miały od czasu PEP 3107 - Adnotacje funkcji ), w którym dołączone są metadane typu:from typing import get_type_hints # grabs __annotations__
Teraz
__main__.__annotations__
zawiera zadeklarowane typy:>>> from typing import List, get_type_hints >>> primes: List[int] = [] >>> captain: str >>> import __main__ >>> get_type_hints(__main__) {'primes': typing.List<~T>[int]}
captain
obecnie nie jest wyświetlany,get_type_hints
ponieważget_type_hints
zwraca tylko typy, do których można również uzyskać dostęp w module; tj. najpierw potrzebuje wartości:>>> captain = "Picard" >>> get_type_hints(__main__) {'primes': typing.List<~T>[int], 'captain': <class 'str'>}
Użycie
print(__annotations__)
pokaże,'captain': <class 'str'>
ale naprawdę nie powinieneś mieć__annotations__
bezpośredniego dostępu .Podobnie dla zajęć:
>>> get_type_hints(Starship) ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})
Gdzie a
ChainMap
jest używany do pobierania adnotacji dla danej klasy (znajdujących się w pierwszym odwzorowaniu) i wszystkich adnotacji zdefiniowanych w klasach bazowych znalezionych w jejmro
(konsekwentne mapowania{}
dla obiektu).Wraz z nową składnią dodano nowy
ClassVar
typ oznaczający zmienne klasowe. Tak,stats
w twoim przykładzie jest w rzeczywistości zmienną instancji , a nieClassVar
.Podobnie jak w przypadku wskazówek dotyczących typów z witryny
PEP 484
, są one całkowicie opcjonalne i służą głównie do sprawdzania typów (i wszystkiego, co można zbudować na podstawie tych informacji). Jest to tymczasowe, gdy zostanie wydana stabilna wersja Pythona 3.6, więc w przyszłości mogą zostać wprowadzone drobne poprawki.źródło