Python 3 Funktionsanmerkungen

Funktionsanmerkungen sind eine Python 3-Funktion, mit der Sie den Funktionsargumenten und dem Rückgabewert beliebige Metadaten hinzufügen können. Sie waren Teil der ursprünglichen Python 3.0-Spezifikation.

In diesem Tutorial zeige ich Ihnen, wie Sie allgemeine Funktionsanmerkungen nutzen und sie mit Dekorateuren kombinieren können. Außerdem erfahren Sie mehr über die Vor- und Nachteile von Funktionsanmerkungen, wann sie verwendet werden sollten und wann andere Mechanismen wie Docstrings und einfache Dekoratoren am besten geeignet sind.

Funktionsanmerkungen

Funktionsanmerkungen werden in PEP-3107 angegeben. Die Hauptmotivation bestand darin, eine Standardmethode für das Zuordnen von Metadaten zu Funktionsargumenten und zum Rückgabewert bereitzustellen. Viele Community-Mitglieder fanden neuartige Anwendungsfälle, verwendeten jedoch unterschiedliche Methoden, z. B. benutzerdefinierte Dekoratore, benutzerdefinierte Docstring-Formate und das Hinzufügen benutzerdefinierter Attribute zum Funktionsobjekt.

Es ist wichtig zu verstehen, dass Python die Anmerkungen nicht mit Semantik segnet. Es bietet lediglich eine nette syntaktische Unterstützung für das Zuordnen von Metadaten sowie eine einfache Möglichkeit, auf sie zuzugreifen. Anmerkungen sind auch völlig optional.

Schauen wir uns ein Beispiel an. Hier ist eine Funktion foo () Das nimmt drei Argumente mit den Namen a, b und c und gibt deren Summe aus. Beachten Sie, dass foo () nichts zurückgibt. Das erste Argument ein wird nicht kommentiert. Das zweite Argument b wird mit der Zeichenfolge 'annotation b' und dem dritten Argument versehen c wird mit Typ kommentiert int. Der Rückgabewert wird mit dem Typ versehen schweben. Beachten Sie die "->" - Syntax zum Annotieren des Rückgabewerts.

python def foo (a, b: 'b' kommentieren, c: int) -> float: print (a + b + c)

Die Anmerkungen haben keinerlei Auswirkungen auf die Ausführung der Funktion. Lass uns anrufen foo () zweimal: einmal mit int-Argumenten und einmal mit String-Argumenten. In beiden Fällen, foo () macht das Richtige, und die Anmerkungen werden einfach ignoriert.

"python foo ('Hallo', ',', 'Welt!') Hallo, Welt!

foo (1, 2, 3) 6 "

Standardargumente

Standardargumente werden nach der Annotation angegeben:

"python def foo (x: 'ein Argument mit dem Standardwert 5' = 5): print (x)

foo (7) 7

foo () 5 "

Zugriff auf Funktionsanmerkungen

Das Funktionsobjekt hat ein Attribut namens 'Anmerkungen'. Es ist eine Zuordnung, die jeden Argumentnamen seiner Anmerkung zuordnet. Die Rückgabewert-Annotation wird dem Schlüssel 'return' zugeordnet, der mit keinem Argumentnamen in Konflikt stehen kann, da 'return' ein reserviertes Wort ist, das nicht als Argumentname dienen kann. Beachten Sie, dass es möglich ist, ein Schlüsselwortargument namens return an eine Funktion zu übergeben:

"python def bar (* args, ** kwargs: 'die Schlüsselwortargumente dict'): print (kwargs ['return'])

d = 'return': 4 bar (** d) 4 "

Gehen wir zurück zu unserem ersten Beispiel und prüfen Sie die Anmerkungen:

"python def foo (a, b: 'kommentieren von b', c: int) -> float: print (a + b + c)

drucken (foo.Anmerkungen) 'c': , 'b': 'Annotation b', 'Return': "

Das ist ziemlich einfach. Wenn Sie eine Funktion mit einem Argument-Array und / oder einem Keyword-Argument-Array versehen, können Sie offensichtlich keine einzelnen Argumente mit Anmerkungen versehen.

"python def foo (* args: 'Liste der unbenannten Argumente', ** kwargs: 'dict der benannten Argumente'): print (args, kwargs)

drucken (foo.Anmerkungen) 'args': 'Liste der unbenannten Argumente', 'kwargs': 'Dikt der benannten Argumente' "

Wenn Sie den Abschnitt über den Zugriff auf Funktionsanmerkungen in PEP-3107 lesen, heißt es, dass Sie über das Attribut 'func_annotations' des Funktionsobjekts darauf zugreifen. Dies ist seit Python 3.2 nicht mehr aktuell. Sei nicht verwirrt Es ist einfach das 'AnmerkungenAttribut.

Was können Sie mit Anmerkungen tun??

Das ist die große Frage. Anmerkungen haben keine Standardbedeutung oder Semantik. Es gibt verschiedene Kategorien von generischen Verwendungen. Sie können sie als bessere Dokumentation verwenden und die Dokumentation von Argumenten und Rückgabewerten aus dem Docstring verschieben. Zum Beispiel diese Funktion:

python def div (a, b): "" "a durch b args teilen: a - die Dividende b - der Divisor (muss ungleich 0 sein) return: das Ergebnis der Division von a durch b" "" return a / b

Kann umgewandelt werden in:

python def div (a: 'die Dividende', b: 'der Divisor (muss sich von 0 unterscheiden') ') ->' das Ergebnis der Division von a durch b ': "" "a durch b teilen" "" zurückgeben a / b

Während die gleichen Informationen erfasst werden, bietet die Annotationsversion mehrere Vorteile:

  1. Wenn Sie ein Argument umbenennen, ist die Dokumentationsversion des Dokuments möglicherweise veraltet.
  2. Es ist einfacher zu sehen, ob ein Argument nicht dokumentiert ist.
  3. Es ist nicht notwendig, ein spezielles Format für die Argumentationsdokumentation innerhalb des Dokuments anzugeben, das von Tools analysiert werden soll. Das Anmerkungen Attribut bietet einen direkten Standardmechanismus für den Zugriff.

Eine weitere Verwendung, über die wir später sprechen werden, ist die optionale Eingabe. Python ist dynamisch typisiert, dh Sie können jedes Objekt als Argument einer Funktion übergeben. Häufig erfordern Funktionen jedoch Argumente eines bestimmten Typs. Mit Annotationen können Sie den Typ ganz natürlich direkt neben dem Argument angeben.

Denken Sie daran, dass die Angabe des Typs dies nicht erzwingen wird und zusätzliche Arbeit (viel Arbeit) erforderlich ist. Selbst wenn Sie nur den Typ angeben, kann der Intent besser lesbar gemacht werden als durch die Angabe des Typs in der Dokumentzeichenfolge. Außerdem können Benutzer den Aufruf der Funktion besser verstehen.

Ein weiterer Vorteil von Anmerkungen gegenüber Docstring besteht darin, dass Sie verschiedene Arten von Metadaten als Tupel oder Dicts anfügen können. Sie können dies auch mit docstring tun, es wird jedoch textbasiert und erfordert eine spezielle Analyse.

Schließlich können Sie viele Metadaten anfügen, die von speziellen externen Tools oder zur Laufzeit über Dekorateure verwendet werden. Ich werde diese Option im nächsten Abschnitt untersuchen.

Mehrere Anmerkungen

Angenommen, Sie möchten ein Argument sowohl mit seinem Typ als auch mit einer Hilfefolge versehen. Bei Anmerkungen ist dies sehr einfach. Sie können das Argument einfach mit einem Diktieren versehen, das aus zwei Schlüsseln besteht: 'type' und 'help'..

"python def div (a: dict (type = float, help =" die Dividende "), b: dict (type = float, help =" der Divisor (muss anders als 0 sein "))) -> dict (type = float, help = "das Ergebnis der Division von a durch b"): "" "a durch b teilen" "" geben a / b zurück

drucken (div.Anmerkungen) 'a': 'help': 'die Dividende', 'type': float, 'b': 'help': 'der Divisor (muss anders als 0 sein)', 'type': float , 'return': 'help': 'das Ergebnis der Division von a durch b', 'type': float "

Kombinieren von Python-Anmerkungen und Dekorateuren

Anmerkungen und Dekorateure gehen Hand in Hand. Eine gute Einführung in Python-Dekorateure finden Sie in meinen beiden Tutorials: Deep Dive In Python-Dekorateure und Write Your Own Python-Dekorateure.

Erstens können Anmerkungen vollständig als Dekorateure implementiert werden. Sie können einfach eine definieren @kommentieren decorator und lassen Sie einen Argumentnamen und einen Python-Ausdruck als Argumente und speichern Sie sie dann in der Zielfunktion Anmerkungen Attribut. Dies ist auch für Python 2 möglich.

Die wahre Stärke der Dekorateure besteht jedoch darin, dass sie auf die Anmerkungen einwirken können. Dies erfordert natürlich eine Abstimmung über die Semantik von Annotationen.

Schauen wir uns ein Beispiel an. Angenommen, wir möchten überprüfen, ob sich die Argumente in einem bestimmten Bereich befinden. Die Annotation ist ein Tupel mit dem minimalen und maximalen Wert für jedes Argument. Dann benötigen wir einen Dekorator, der die Annotation jedes Keyword-Arguments überprüft, überprüft, ob der Wert innerhalb des Bereichs liegt, und ansonsten eine Ausnahme auslösen. Beginnen wir mit dem Dekorateur:

python def check_range (f): def Dekor (* args, ** kwargs): Name, Bereich in f .__ Anmerkungen __. items (): min_value, max_value = range falls nicht (min_value <= kwargs[name] <= max_value): msg = 'argument is out of range [ - ]' raise ValueError(msg.format(name, min_value, max_value)) return f(*args, **kwargs) return decorated

Nun definieren wir unsere Funktion und verzieren sie mit @check_range Dekorateure.

Python @check_range def foo (a: (0, 8), b: (5, 9), c: (10, 20)): Rückgabe a * b - c

Lass uns anrufen foo () mit verschiedenen Argumenten und sehen, was passiert. Wenn alle Argumente innerhalb ihres Bereichs liegen, gibt es kein Problem.

Pythonfoo (a = 4, b = 6, c = 15) 9

Wenn wir c auf 100 setzen (außerhalb des Bereichs (10, 20)), wird eine Ausnahme ausgelöst:

python foo (a = 4, b = 6, c = 100) ValueError: Argument c liegt außerhalb des Bereichs [10 - 20]

Wann sollten Sie Dekorateure anstelle von Anmerkungen verwenden??

Es gibt mehrere Situationen, in denen Dekorateure besser als Anmerkungen zum Anhängen von Metadaten sind.

Ein offensichtlicher Fall ist, wenn Ihr Code mit Python 2 kompatibel sein muss.

Ein anderer Fall ist, wenn Sie viele Metadaten haben. Wie Sie bereits gesehen haben, ist es zwar möglich, jede Menge Metadaten mithilfe von Diktaten als Anmerkungen anzufügen. Dies ist jedoch ziemlich umständlich und beeinträchtigt die Lesbarkeit.

Wenn schließlich die Metadaten von einem bestimmten Dekorateur bearbeitet werden sollen, ist es möglicherweise besser, die Metadaten als Argumente für den Dekorateur selbst zu verwenden.

Dynamische Anmerkungen

Anmerkungen sind nur ein Diktierattribut einer Funktion.

Python-Typ (Foo .__ Annotations__) Dikt

Dies bedeutet, dass Sie sie während der Ausführung des Programms jederzeit ändern können. Was sind einige Anwendungsfälle? Angenommen, Sie möchten herausfinden, ob ein Standardwert eines Arguments jemals verwendet wird. Wenn die Funktion mit dem Standardwert aufgerufen wird, können Sie den Wert einer Anmerkung erhöhen. Oder Sie möchten vielleicht alle Rückgabewerte zusammenfassen. Der dynamische Aspekt kann innerhalb der Funktion selbst oder von einem Dekorateur ausgeführt werden.

"Python def add (a, b) -> 0: Ergebnis = a + b add.Anmerkungen['return'] + = result Ergebnis

drucken (add.Anmerkungen['return']) 0

add (3, 4) 7 drucken (add.Anmerkungen['return']) 7

add (5, 5) 10 drucken (add.Anmerkungen['return']) 17 "

Fazit

Funktionsanmerkungen sind vielseitig und aufregend. Sie haben das Potenzial, eine neue Ära introspektiver Tools einzuleiten, mit denen Entwickler immer komplexere Systeme beherrschen können. Sie bieten dem fortgeschrittenen Entwickler auch eine standardisierte und lesbare Methode, um Metadaten direkt mit Argumenten zu verknüpfen und Werte zurückzugeben, um benutzerdefinierte Werkzeuge zu erstellen und mit Dekorateuren zu interagieren. Es bedarf jedoch einiger Arbeit, um von ihnen zu profitieren und ihr Potenzial auszuschöpfen.

Lerne Python

Lernen Sie Python mit unserem kompletten Python-Tutorial, egal ob Sie gerade erst anfangen oder ein erfahrener Programmierer sind, der neue Fähigkeiten erlernen möchte.