Heute veröffentlichen wir den zweiten Teil einer Übersetzung des Materials, die sich mit Typanmerkungen in Python befasst.

→
Der erste TeilWie unterstützt Python Datentypen?
Python ist eine dynamisch typisierte Sprache. Dies bedeutet, dass die verwendeten Variablentypen nur während der Programmausführung überprüft werden. In dem Beispiel im vorherigen Teil des Artikels konnte man sehen, dass ein Programmierer, der in Python schreibt, die Variablentypen nicht planen und darüber nachdenken musste, wie viel Speicher zum Speichern seiner Daten benötigt würde.
Folgendes passiert, wenn Sie Ihren Python-Code für die Ausführung vorbereiten: „In Python wird der Quellcode mithilfe von CPython in eine viel einfachere Form namens Bytecode konvertiert. Der Bytecode besteht aus Anweisungen, die im Wesentlichen Prozessoranweisungen ähnlich sind. Sie werden jedoch nicht vom Prozessor ausgeführt, sondern von einem Softwaresystem, das als virtuelle Maschine bezeichnet wird. (Hier geht es nicht um virtuelle Maschinen, mit deren Funktionen Sie ganze Betriebssysteme auf ihnen ausführen können. In unserem Fall handelt es sich um eine vereinfachte Version der Umgebung, die Programmen zur Verfügung steht, die auf dem Prozessor ausgeführt werden.)
Woher weiß CPython, welche Variablentypen verwendet werden sollen, wenn ein Programm für die Ausführung vorbereitet wird? Immerhin haben wir diese Typen nicht angegeben. CPython weiß davon nichts. Er weiß nur, dass Variablen Objekte sind. Alles in Python ist ein
Objekt , zumindest bis sich herausstellt, dass etwas einen spezifischeren Typ hat.
Beispielsweise betrachtet Python als Zeichenfolge alles, was in einfache oder doppelte Anführungszeichen eingeschlossen ist. Wenn Python auf eine Zahl stößt, wird davon ausgegangen, dass der entsprechende Wert vom numerischen Typ ist. Wenn wir versuchen, etwas mit einer Entität zu tun, das mit einer Entität ihres Typs nicht möglich ist, wird Python uns dies später mitteilen.
Beachten Sie die folgende Fehlermeldung, die angezeigt wird, wenn Sie versuchen, eine Zeichenfolge und eine Zahl hinzuzufügen:
name = 'Vicki' seconds = 4.71; --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-9-71805d305c0b> in <module> 3 4 ----> 5 name + seconds TypeError: must be str, not float
Das System teilt uns mit, dass es keine Zeichenfolgen und Gleitkommazahlen hinzufügen kann. Darüber hinaus interessierte die Tatsache, dass
name
eine Zeichenfolge und
seconds
eine Zahl ist, das System nicht, bis versucht wurde,
name
und
seconds
hinzuzufügen.
Mit anderen Worten, es kann
wie folgt beschrieben
werden : „Bei der Addition wird die Ententypisierung verwendet. Python interessiert sich nicht dafür, welchen Typ ein bestimmtes Objekt hat. Das System interessiert sich nur dafür, ob es einen sinnvollen Aufruf an die Additionsmethode zurückgibt. Ist dies nicht der Fall, wird ein Fehler ausgegeben. "
Was würde das bedeuten? Dies bedeutet, dass wir beim Schreiben von Programmen in Python keine Fehlermeldung erhalten, bis der CPython-Interpreter mit der Ausführung derselben Zeile beschäftigt ist, in der ein Fehler vorliegt.
Dieser Ansatz war unpraktisch, wenn er in Teams angewendet wurde, die an großen Projekten arbeiteten. Tatsache ist, dass sie in solchen Projekten nicht mit separaten Variablen arbeiten, sondern mit komplexen Datenstrukturen. In solchen Projekten werden einige Funktionen von anderen aufgerufen, und diese wiederum werden von einigen anderen Funktionen aufgerufen. Teammitglieder sollten in der Lage sein, den Code für ihre Projekte schnell zu überprüfen. Wenn sie nicht in der Lage sind, gute Tests zu schreiben, die Fehler in Projekten erkennen, bevor sie in Produktion gehen, bedeutet dies, dass solche Projekte große Probleme erwarten können.
Genau genommen kommen wir hier zum Gespräch über Typanmerkungen in Python.
Wir können sagen, dass die Verwendung von Typanmerkungen im Allgemeinen viele
Stärken hat . Wenn Sie mit komplexen Datenstrukturen oder Funktionen arbeiten, die viele Eingabewerte annehmen, vereinfacht die Verwendung von Anmerkungen die Arbeit mit ähnlichen Strukturen und Funktionen erheblich. Besonders - einige Zeit nach ihrer Entstehung. Wenn Sie nur eine Funktion mit einem Parameter haben, wie in den hier angegebenen Beispielen, ist die Arbeit mit einer solchen Funktion auf jeden Fall sehr einfach.
Was ist, wenn wir mit komplexen Funktionen arbeiten müssen, die viele ähnliche Eingabewerte aus der
PyTorch- Dokumentation übernehmen:
def train(args, model, device, train_loader, optimizer, epoch): model.train() for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) loss.backward() optimizer.step() if batch_idx % args.log_interval == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))
Was ist ein
model
? Natürlich können wir uns in die Codebasis vertiefen und herausfinden:
model = Net().to(device)
Es wäre jedoch schön, wenn Sie nur den
model
in der Funktionssignatur angeben und sich vor unnötiger Code-Analyse schützen könnten. Vielleicht würde es so aussehen:
def train(args, model (type Net), device, train_loader, optimizer, epoch):
Was ist mit
device
? Wenn Sie den Code durchsuchen, können Sie Folgendes herausfinden:
device = torch.device("cuda" if use_cuda else "cpu")
Jetzt stehen wir vor der Frage, was
torch.device
. Dies ist eine spezielle Art von PyTorch. Die Beschreibung finden Sie im
entsprechenden Abschnitt der PyTorch-Dokumentation.
Es wäre schön, wenn wir den Typ
device
in der Argumentliste der Funktion angeben könnten. Somit würden wir viel Zeit für diejenigen sparen, die diesen Code analysieren müssten.
def train(args, model (type Net), device (type torch.Device), train_loader, optimizer, epoch):
Diese Überlegungen können sehr lange dauern.
Infolgedessen stellt sich heraus, dass Typanmerkungen für jemanden, der Code schreibt, sehr nützlich sind. Sie kommen aber auch denen zugute, die den Code anderer lesen. Es ist viel einfacher, getippten Code als Code zu lesen, um zu verstehen, mit welcher Entität Sie umgehen müssen. Typanmerkungen verbessern die Lesbarkeit des Codes.
Was wurde in Python getan, um den Code auf die gleiche Lesbarkeit zu bringen, die Code unterscheidet, der in statisch typisierten Sprachen geschrieben wurde?
Geben Sie Anmerkungen in Python ein
Jetzt sind wir bereit, ernsthaft über Typanmerkungen in Python zu sprechen. Beim Lesen von in Python 2 geschriebenen Programmen konnte man sehen, dass die Programmierer ihren Code mit Hinweisen versorgten, die den Lesern des Codes mitteilten, welchen Typ die von den Funktionen zurückgegebenen Variablen oder Werte haben.
Ein ähnlicher Code sah ursprünglich so aus:
users = []
Typanmerkungen waren früher einfache Kommentare. Aber so kam es, dass Python allmählich zu einer einheitlicheren Art des Umgangs mit Anmerkungen überging. Insbesondere sprechen wir über die Entstehung des Dokuments
PEP 3107 , das der Annotation von Funktionen gewidmet ist.
Als nächstes begannen die Arbeiten an
PEP 484 . Dieses Dokument, das Typanmerkungen gewidmet ist, wurde in enger Verbindung mit mypy, dem DropBox-Projekt, entwickelt, das darauf abzielt, Typen vor dem Ausführen von Skripten zu überprüfen. Bei der Verwendung von mypy ist zu beachten, dass während der Skriptausführung keine Typprüfung durchgeführt wird. Zur Laufzeit kann eine Fehlermeldung empfangen werden, wenn Sie beispielsweise versuchen, einen Typ zu erstellen, den dieser Typ nicht unterstützt. Sagen Sie - wenn Sie versuchen, ein Wörterbuch in Scheiben zu schneiden oder die
.pop()
-Methode für eine Zeichenfolge
.pop()
.
In PEP 484 erfahren Sie Folgendes über die Details der Annotationsimplementierung: „Obwohl diese Annotationen zur Laufzeit über das Attribut für reguläre
annotations
verfügbar sind, werden zur Laufzeit keine Typprüfungen durchgeführt. Stattdessen sieht dieser Vorschlag die Existenz eines separaten unabhängigen Tools zur Überprüfung von Typen vor, mit dem der Benutzer auf Wunsch den Quellcode seiner Programme überprüfen kann. Im Allgemeinen funktioniert ein ähnliches Tool zur Typprüfung wie ein sehr leistungsfähiger Linter. "Natürlich können einzelne Benutzer ein ähnliches Tool zum Überprüfen von Typen zur Laufzeit verwenden, entweder für die Implementierung der Design By Contract-Methodik oder für die Implementierung der JIT-Optimierung. Es sollte jedoch beachtet werden, dass solche Tools noch nicht ausreichend ausgereift sind."
Wie sieht die Arbeit mit Typanmerkungen in der Praxis aus?
Ihre Verwendung bedeutet beispielsweise die Möglichkeit, die Arbeit in verschiedenen IDEs zu erleichtern.
PyCharm bietet also basierend auf
Typinformationen die Vervollständigung und Überprüfung des Codes an. Ähnliche Funktionen sind in VS Code verfügbar.
Typanmerkungen sind aus einem weiteren Grund nützlich: Sie schützen den Entwickler vor dummen Fehlern.
Hier ist ein gutes Beispiel für einen solchen Schutz.
Angenommen, wir fügen dem Wörterbuch die Namen von Personen hinzu:
names = {'Vicki': 'Boykis', 'Kim': 'Kardashian'} def append_name(dict, first_name, last_name): dict[first_name] = last_name append_name(names,'Kanye',9)
Wenn wir dies zulassen, gibt es viele falsch geformte Einträge im Wörterbuch.
Lassen Sie uns das beheben:
from typing import Dict names_new: Dict[str, str] = {'Vicki': 'Boykis', 'Kim': 'Kardashian'} def append_name(dic: Dict[str, str] , first_name: str, last_name: str): dic[first_name] = last_name append_name(names_new,'Kanye',9.7) names_new
Überprüfen Sie nun diesen Code mit mypy und erhalten Sie Folgendes:
(kanye) mbp-vboykis:types vboykis$ mypy kanye.py kanye.py:9: error: Argument 3 to "append_name" has incompatible type "float"; expected "str"
Es ist ersichtlich, dass mypy es Ihnen nicht erlaubt, die Nummer zu verwenden, unter der die Zeichenfolge erwartet wird. Diejenigen, die solche Tests regelmäßig verwenden möchten, sollten mypy einbeziehen, wenn Codetests in ihren kontinuierlichen Integrationssystemen durchgeführt werden.
Geben Sie Hinweise in verschiedene IDEs ein
Einer der wichtigsten Vorteile der Verwendung von Typanmerkungen besteht darin, dass Python-Programmierer dieselben Code-Vervollständigungsfunktionen in verschiedenen IDEs verwenden können, die für statisch typisierte Sprachen verfügbar sind.
Angenommen, Sie haben einen Code, der dem folgenden ähnelt. Dies sind einige Funktionen aus früheren Beispielen, die in Klassen eingeschlossen sind.
from typing import Dict class rainfallRate: def __init__(self, hours, inches): self.hours= hours self.inches = inches def calculateRate(self, inches:int, hours:int) -> float: return inches/hours rainfallRate.calculateRate() class addNametoDict: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name self.dict = dict def append_name(dict:Dict[str, str], first_name:str, last_name:str): dict[first_name] = last_name addNametoDict.append_name()
Das Schöne ist, dass wir aus eigener Initiative dem Code Typbeschreibungen hinzugefügt haben. Wir können beobachten, was im Programm passiert, wenn die Klassenmethoden aufgerufen werden:
Tipps zum IDE-TypErste Schritte mit Typanmerkungen
In der Dokumentation zu mypy finden Sie gute Empfehlungen dazu, wie Sie mit der Eingabe der Codebasis beginnen sollen:
- Fangen Sie klein an - stellen Sie sicher, dass einige Dateien mit mehreren Anmerkungen mit mypy validiert sind.
- Schreiben Sie ein Skript, um mypy auszuführen. Dies wird dazu beitragen, konsistente Testergebnisse zu erzielen.
- Führen Sie mypy in CI-Pipelines aus, um Typfehler zu vermeiden.
- Kommentieren Sie nach und nach die Module, die im Projekt am häufigsten verwendet werden.
- Fügen Sie dem vorhandenen Code, den Sie ändern, Typanmerkungen hinzu. rüste sie mit dem neuen Code aus, den du schreibst.
- Verwenden Sie MonkeyType oder PyAnnotate, um alten Code automatisch mit Anmerkungen zu versehen.
Bevor Sie mit dem Kommentieren Ihres eigenen Codes beginnen, sollten Sie sich mit etwas befassen.
Zunächst müssen Sie das
Typisierungsmodul in den Code importieren, wenn Sie etwas anderes als Zeichenfolgen, Ganzzahlen, Boolesche Werte und die Werte anderer grundlegender Python-Typen verwenden.
Zweitens ermöglicht dieses Modul die Arbeit mit mehreren komplexen Typen. Darunter sind
Dict
,
Tuple
,
List
und
Set
. Eine Konstruktion der Form
Dict[str, float]
bedeutet, dass Sie mit einem Wörterbuch arbeiten möchten, dessen Elemente eine Zeichenfolge als Schlüssel und eine Gleitkommazahl als Wert verwenden. Es gibt auch Typen namens
Optional
und
Union
.
Drittens müssen Sie sich mit dem Format der Typanmerkungen vertraut machen:
import typing def some_function(variable: type) -> return_type: do_something
Wenn Sie mehr darüber erfahren möchten, wie Sie Typanmerkungen in Ihren Projekten anwenden können, möchte ich darauf hinweisen, dass viele gute Tutorials diesem Thema gewidmet sind.
Hier ist einer von ihnen. Ich halte es für das Beste. Nachdem Sie es beherrschen, lernen Sie die Code-Annotation und ihre Überprüfung kennen.
Die Ergebnisse. Lohnt es sich, Typanmerkungen in Python zu verwenden?
Fragen wir uns nun, ob Sie in Python Typanmerkungen verwenden sollten. Eigentlich hängt es von den Funktionen Ihres Projekts ab. Dazu sagt Guido van Rossum in der Dokumentation zu mypy: „Der Zweck von mypy besteht nicht darin, alle davon zu überzeugen, statisch typisierten Python-Code zu schreiben. Die statische Eingabe ist jetzt und in Zukunft völlig optional. Mypys Ziel ist es, Python-Programmierern mehr Optionen zu bieten. Damit soll Python zu einer wettbewerbsfähigeren Alternative zu anderen statisch typisierten Sprachen werden, die in großen Projekten verwendet werden. Es soll die Produktivität der Programmierer steigern und die Qualität der Software verbessern. "
Die Zeit, die erforderlich ist, um mypy zu konfigurieren und die für ein bestimmtes Programm erforderlichen Typen zu planen, rechtfertigt sich nicht in kleinen Projekten und während Experimenten (z. B. in Jupyter). Welches Projekt sollte als klein angesehen werden? Wahrscheinlich derjenige, dessen Volumen nach sorgfältigen Schätzungen 1000 Zeilen nicht überschreitet.
Typanmerkungen sind in größeren Projekten sinnvoll. Dort können sie insbesondere viel Zeit sparen. Wir sprechen über Projekte, die von Gruppen von Programmierern entwickelt wurden, über Pakete, über Code, die bei der Entwicklung von Versionskontrollsystemen und CI-Pipelines verwendet werden.
Ich glaube, dass Typanmerkungen in den nächsten Jahren viel häufiger auftreten werden als jetzt, ganz zu schweigen von der Tatsache, dass sie sich möglicherweise zu einem normalen alltäglichen Werkzeug entwickeln. Und ich glaube, dass jemand, der vor den anderen mit ihnen arbeitet, nichts verlieren wird.
Liebe Leser! Verwenden Sie Typanmerkungen in Ihren Python-Projekten?
