Was sind variable Annotationen in Python 3.6?

83

Python 3.6 steht kurz vor der Veröffentlichung. PEP 494 - Python 3.6 Release Schedule erwähnt Ende Dezember, daher habe ich die Neuerungen in Python 3.6 durchgesehen, um zu sehen, dass sie die variablen Anmerkungen erwähnen :

Mit PEP 484 wurde ein Standard für Typanmerkungen von Funktionsparametern eingeführt, auch bekannt als Typhinweise. Dieser PEP fügt Python eine Syntax zum Kommentieren der Variablentypen hinzu, einschließlich Klassenvariablen und Instanzvariablen:

primes: List[int] = []

captain: str  # Note: no initial value!

class Starship:
     stats: Dict[str, int] = {}

Genau wie bei Funktionsanmerkungen misst der Python-Interpreter Variablenanmerkungen keine besondere Bedeutung bei und speichert sie nur in einem speziellen Attribut __annotations__einer Klasse oder eines Moduls. Im Gegensatz zu Variablendeklarationen in statisch typisierten Sprachen besteht das Ziel der Anmerkungssyntax darin, auf einfache Weise strukturierte Typmetadaten für Tools und Bibliotheken von Drittanbietern über den abstrakten Syntaxbaum und das __annotations__Attribut anzugeben .

Also von dem, was ich lese sie sind Teil der Typ Hinweise von Python kommen 3.5, beschrieben in Was Typ Hinweise in Python sind 3.5 .

Ich folge dem Beispiel captain: strund bin mir class Starshipaber nicht sicher, was das letzte angeht: Wie erklärt sich primes: List[int] = []das? Definiert es eine leere Liste, die nur ganze Zahlen zulässt?

fedorqui 'SO hör auf zu schaden'
quelle
9
Type Hints Sie nicht tun , jede Art Prüfung. primes: List[int] = []ist nur eine leere Liste als primes = []. Der Unterschied ist , dass Sie behaupten , dass primes soll dich auf nur enthalten ints und 3rd - Party - Anwendungen möglicherweise geben Sie Ihr Programm überprüfen , diese Behauptung zu überprüfen, aber wenn Sie den Code in jedem Python - Interpreter ausführen , die genau das gleiche wie das Schreiben ist primes = [], und so tun , primes: List[int] = []; primes.append("string")ist nach wie vor gültig.
Bakuriu
2
@ Bakuriu ja, guter Punkt. Wie Jim Fasarakis-Hilliard in seiner Antwort auf Was sind Typhinweise in Python 3.5 beschreibt , warum TyphinweiseHilft Typprüfungen, hilft bei der Dokumentation und hilft IDEs, genauere und robustere Tools zu entwickeln . Aus PEP 526 - Syntax für variable Annotationen entnommen , bleibt Python eine dynamisch typisierte Sprache, und die Autoren möchten auch nach Konvention niemals Typhinweise verbindlich machen .
Fedorqui 'SO hör auf zu schaden'
1
Beantwortet das deine Frage? Was sind Typhinweise in Python 3.5?
AMC

Antworten:

46

Alles zwischen :und =ist ein Typhinweis, wird also primestatsächlich als definiert List[int]und zunächst auf eine leere Liste gesetzt (und statsist zunächst ein leeres Wörterbuch, definiert als Dict[str, int]).

List[int]und Dict[str, int]sind nicht Teil der nächsten Syntax, diese wurden jedoch bereits in den Python 3.5-Tipphinweisen PEP definiert. Der Vorschlag 3.6 PEP 526 - Syntax für Variablenanmerkungen definiert nur die Syntax zum Anhängen derselben Hinweise an Variablen. zuvor konnten Sie Variablen mit Kommentaren (z primes = [] # List[int]. B. ) nur Typhinweise hinzufügen .

Beide Listund Dictsind generische Typen, die angeben, dass Sie eine Listen- oder Wörterbuchzuordnung mit bestimmten (konkreten) Inhalten haben.

Denn Listes gibt nur ein 'Argument' (die Elemente in der [...]Syntax), den Typ jedes Elements in der Liste. Für Dictist das erste Argument der Schlüssel - Typ und der zweite ist der Wert ein. Also alle Werte in der primesListe ganze Zahlen sind, und alle Schlüssel-Wert - Paare im statsWörterbuch sind (str, int)Paare, Strings auf ganze Zahlen abbildet.

Siehe die typing.Listund typing.DictDefinitionen, den Abschnitt über Generika sowie PEP 483 - The Theory of Type Hints .

Wie Typhinweise zu Funktionen ist ihre Verwendung optional und wird auch als Annotation betrachtet (vorausgesetzt, es gibt ein Objekt, an das diese angehängt werden können, also Globale in Modulen und Attributen in Klassen, aber keine Einheimischen in Funktionen), die Sie über das __annotations__Attribut überprüfen können . Sie können diesen Anmerkungen beliebige Informationen hinzufügen. Sie sind nicht streng darauf beschränkt, Hinweisinformationen einzugeben.

Vielleicht möchten Sie den vollständigen Vorschlag lesen . Es enthält einige zusätzliche Funktionen, die über die neue Syntax hinausgehen. Es gibt an, wann solche Annotationen ausgewertet werden, wie sie überprüft werden und wie beispielsweise etwas als Klassenattribut oder Instanzattribut deklariert wird.

Martijn Pieters
quelle
Darf ich Typhinweise als eine Art "maschinenlesbare" Kommentare betrachten, da sie keinen Einfluss darauf haben, wie der Code ausgeführt wird (mit Ausnahme eines obj.__annotations__Attributs)?
iBug
1
@iBug: Anmerkungen sind maschinenlesbare Kommentare, sofern Kommentare ohnehin lesbare Anmerkungen sind. :-)
Martijn Pieters
56

Was sind variable Anmerkungen?

Variable Anmerkungen sind nur der nächste Schritt von # typeKommentaren, wie sie in definiert wurden PEP 484. Die Gründe für diese Änderung werden im jeweiligen Abschnitt von PEP 526 hervorgehoben .

Anstatt den Typ mit folgenden Hinweisen zu versehen:

primes = []  # type: List[int]

Es wurde eine neue Syntax eingeführt , mit der der Typ direkt mit einer Zuweisung des Formulars versehen werden kann:

primes: List[int] = []

Dies bezeichnet, wie @Martijn hervorhob, eine Liste von Ganzzahlen, indem die in verfügbaren Typen verwendet typingund in eine leere Liste initialisiert werden.

Welche Veränderungen bringt es?

Die erste eingeführte Änderung war eine neue Syntax , mit der Sie einen Namen mit einem Typ versehen können, entweder eigenständig nach dem :Zeichen oder optional mit Anmerkungen versehen und ihm gleichzeitig einen Wert zuweisen können:

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

Also das fragliche Beispiel:

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

Mit der neuen Syntax wurden auch zusätzliche Änderungen eingeführt. Module und Klassen haben jetzt ein __annotations__Attribut (wie es Funktionen seit PEP 3107 - Funktionsanmerkungen hatten ), an das die Typmetadaten angehängt sind:

from typing import get_type_hints  # grabs __annotations__

Nun __main__.__annotations__enthält die deklarierten Typen:

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captainwird derzeit nicht angezeigt, get_type_hintsda get_type_hintsnur Typen zurückgegeben werden, auf die auch in einem Modul zugegriffen werden kann. dh es braucht zuerst einen Wert:

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

Die Verwendung print(__annotations__)wird angezeigt, 'captain': <class 'str'>aber Sie sollten wirklich nicht __annotations__direkt darauf zugreifen .

Ebenso für Klassen:

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

Wobei a ChainMapverwendet wird, um die Annotationen für eine bestimmte Klasse (in der ersten Zuordnung) und alle Annotationen abzurufen, die in den Basisklassen definiert sind, die in ihrer mroZuordnung gefunden wurden (nachfolgende Zuordnungen {}für Objekt).

Zusammen mit der neuen Syntax wurde ein neuer ClassVarTyp hinzugefügt, um Klassenvariablen zu kennzeichnen. Ja, statsin Ihrem Beispiel handelt es sich tatsächlich um eine Instanzvariable , nicht um eine ClassVar.

Werde ich gezwungen sein, es zu benutzen?

Wie bei Typhinweisen von PEP 484sind diese vollständig optional und werden hauptsächlich für Tools zur Typprüfung verwendet (und was auch immer Sie basierend auf diesen Informationen erstellen können). Es soll vorläufig sein, wenn die stabile Version von Python 3.6 veröffentlicht wird, damit in Zukunft möglicherweise kleine Änderungen hinzugefügt werden.

Dimitris Fasarakis Hilliard
quelle