Transkripte
1. Einführung: Hallo, es tut mir leid, ich freue
mich über diesen Kurs, Python-Programmierung für
Fortgeschrittene bis Fortgeschrittene
vermittelt. Dies ist ein kuratierter Kurs. Es ist keine vollständige Liste
aller möglichen
erweiterten Funktionen , die in Python verfügbar sind. Es enthält die Dinge, von denen ich
denke, dass sie für Sie am
nützlichsten sind wenn Sie den nächsten Schritt in Ihrer Karriere als
Softwareentwickler machen
möchten . Dieser Kurs ist für
Sie, wenn Sie Python kennen, aber ein bisschen mehr über
die erweiterten Funktionen
der Sprache
erfahren möchten. Ich werde also
über Dinge wie
Typhinweise, gleichzeitigen Code,
Protokollklassen,
Iteratoren, Generatoren
und ein paar andere
Dinge sprechen Typhinweise, gleichzeitigen Code, Protokollklassen,
Iteratoren, Generatoren . Alle Codebeispiele
,
die im Kurs verwendet werden, finden Sie ,
die im Kurs verwendet werden, auf der Registerkarte Projekte
und Ressourcen. Und am Ende gibt es auch ein lustiges
kleines Projekt , in das
du eintauchen kannst.
Wenn dir dieser Kurs gefällt, magst
du vielleicht auch meinen
YouTube-Kanal oder junge Colts, youtube.com Slash Iron Codes. Dort habe ich hauptsächlich
über Softwaredesign und
verschiedene Arten von
Python-Inhalten gesprochen . Also schau es dir an. Ich hoffe, Ihnen hat der Kurs gefallen,
da Sie bereit sind. Lass uns eintauchen.
2. Typ Anmerkungen 1/3: Ich werde
diesen Kurs beginnen, indem über Typsysteme
spreche. In vielen Programmiersprachen
sind Typen in
ihre Syntax integriert , und es gibt verschiedene
Sichtweisen auf Typsysteme. Und ich möchte heute über
einige davon sprechen und darüber, wie
das mit der Art und Weise zusammenhängt, wie Typen
in Python behandelt werden. Das erste ist also, dass wir
statische und dynamische
Typsysteme haben . Und bei dieser Unterscheidung geht es darum wann die
Typinformation erfasst wird, was würde statisch passieren? Das bedeutet, dass es zur
Kompilierungs- oder Interpretierzeit
passiert ,
wenn es dynamisch ist, es bedeutet, dass die Typen zur Laufzeit bestimmt
werden. Ein weiterer Unterschied, von dem Sie
vielleicht gehört haben ist starkes und schwaches Tippen. Und hier geht es eher darum, wie
streng man konsequent bindet. Konvertiert es zB automatisch
Ganzzahlen in Zeichenketten oder
umgekehrt? Es gibt keine klare
Definition dafür, was genau
ein starkes Tippsystem
im Vergleich zu einem schwachen Tippsystem ist. Aus diesem Grund
suchen wir im Allgemeinen nach anderen Möglichkeiten, Typsysteme zu unterscheiden, über die ich gleich sprechen werde. Jede Programmiersprache
geht anders an Typen heran. Beispielsweise ist Java statisch typisiert. Das heißt,
wenn Sie
eine Variable vom Typ
Zeichenfolge und Zeichenfolge deklarieren und dann versuchen, ihr eine Zahl
zuzuweisen. Das ist nicht erlaubt. Und der Grund, warum es nicht erlaubt
ist,
ist, dass wir bei der
Kompilierung definiert haben , dass die Variable vom Typ String sein soll, sodass wir das nicht mehr ändern können. Python hingegen
ist dynamisch duct,
daher ist es völlig in Ordnung, eine Variable zu definieren und
ihr einen Zeichenkettenwert zu geben. Und später weisen wir
ihm einen Wert eines anderen Typs zu. Im Grunde ist der Typ nicht mit der Variablen
verknüpft, er ist
mit dem Wert i verknüpft. Sehr einfaches Python-Programm hier. Wenn ich also eine Variable
x definiere und eine Zeichenfolge zuweise, und weil Python dynamisch typisiert
ist, kann
ich ihr einfach einen
Wert verschiedener Typen zuweisen, in diesem Fall eine Ganzzahl, und das ist völlig in Ordnung. Es ist überhaupt kein Problem. In Java würde dies
natürlich zu einem Fehler führen. Obwohl Python dynamisch typisiert
ist, es auch ziemlich streng. Man könnte es tatsächlich stark
getippt
nennen , wenn wir
dafür eine Definition hätten. Was ich zum Beispiel tun kann, ist, wenn wir dieselbe Variable X
haben, können
wir Hallo plus fünf machen. Denn wenn ich versuchen würde, das auszuführen, dann siehst du, dass du die Fehlermeldung
bekommst, hey, wir können nur
Zeichenketten und keine Ganzzahlen verketten. Das bedeutet also, dass Python diese Zahl
fünf
nicht automatisch in eine Zeichenfolge fünf umwandelt. Natürlich kann ich
das explizit tun. Wenn ich das Programm also erneut starte, sehen Sie
jetzt, dass es
kein Problem geben wird , denn wenn ich
die Typkonvertierung selbst rückgängig mache, unterscheidet sich
das von einer
Sprache wie JavaScript
, mit der Sie
Hallo plus fünf machen können. Und dann
wandle ich die Zahl einfach
automatisch
in eine Zeichenfolge um . Und es ist auch aus
JavaScript-Sicht sinnvoll ,
denn was JavaScript ist, ist natürlich die
Sprache des Webs. Und wir wollen
sicherstellen, dass der Kunde immer zumindest
etwas Vernünftiges zeigt. JavaScript versucht also sein Bestes, um mit den Werten,
die es erhält, alles zu tun, was es kann. funktioniert nicht immer, aber es bedeutet, dass selbst wenn
eine Webseite einige Fehler aufweist, sie dennoch
etwas Sinnvolles anzeigen kann. Was sind einige andere Möglichkeiten, die Typsysteme zu
betrachten , während eines manifeste oder abgeleitete Typsystem ist, Manifest bedeutet, dass Sie den
Variablentyp
explizit angeben müssen , z. B. C oder Java haben eine Manifesttypisierung, wir müssen angeben,
was der Typ ist. Abgeleitet. Eingabe bedeutet
, dass der Typ der Variablen aus dem Wert
abgeleitet wird. Und genau das
passiert in Python. Python müssen wir also nicht angeben, dass in diesem Fall x eine Zeichenfolge ist und
nichts anderes. Eine andere Betrachtungsweise von
Typsystemen
besteht jedoch darin, nominale und strukturelle Systeme zu betrachten. Nominal bedeutet, dass das Typsystem
sich die Namen vollständig ansieht, um
zu vergleichen, ob die Typen übereinstimmen. Wenn wir also Dinge haben, die
Zeichenketten sind, dann sind sie
beide vom gleichen Typ. Wenn wir zwei
Dinge
derselben Klasse oder auch Klassen haben , dann stimmen die
Typen überein. Das ist nominell. Strukturell bedeutet, dass
wir uns die Struktur von
Objekten ansehen , um zu vergleichen,
ob diese Typen übereinstimmen. Wenn wir also z. B. ein Objekt haben,
das eine Eigenschaft x hat, dann stimmen die Typen
mit einem anderen Objekt überein wenn
das Objekt auch dieselbe Eigenschaft x hat. also wirklich die Struktur
des Objekts im Vergleich zum
Namen des Objekts
an . Also, was
hat Python in diesem Fall? Nun, es ist nicht wirklich
struktureller Typisierung, aber es ist irgendwie ähnlich. Es ist etwas, das Duck Typing
genannt wird. Ententippen ist wie eine
strukturelle Straffung, aber es ist nicht genau dasselbe. Structural Typing ist ein
statisches Typsystem, das die Strukturen von
Objekten
vergleicht , wenn Sie den Code
kompilieren. Doctype ist dynamisch, betrachtet aber nur die
wichtigen Teile. Wir haben also einen bestimmten Teil
des Objekts, auf den Sie zur Laufzeit
zugreifen. Nehmen wir an, Sie haben
ein Objekt mit einer Eigenschaft x und einer Eigenschaft warum? Und zur Laufzeit
greifen Sie nur auf Eigenschaft
X zu, dann stimmen die Typen überein, wenn
das Objekt diese Eigenschaft hat und wir uns die Eigenschaft nicht
ansehen. Warum, obwohl es Teil des statischen Typs
sein könnte, Python
eigentlich
Duck Typing. Es schaut sich also einfach
die Teile an , die während der Laufzeit
benötigt werden. Spiel. Python ist startklar. Ich habe hier ein Beispiel, das
zeigt, wie das Tippen von Enten funktioniert. Also ich habe hier ein
paar Variablen, meine Zeichenfolge oder Liste,
mein Wörterbuch. Und obwohl sie jeweils einige Werte
haben, sehen Sie, haben wir eine Funktionslänge, die die
Länge dieser Dinge ausdrucken
kann. Das ist also keine 11. Klasse
, weil sie 11 Zeichen hat. Das heißt vier,
weil die
Liste vier Elemente enthält und drei davon gedruckt
werden. Und das funktioniert
so, dass die Längenfunktion ein Objekt
erwartet. Sie können es
hier bereits in Schriftgröße sehen. Und das bedeutet, dass diesem
Objekt
eine Lynn-Dunder-Methode
zugeordnet sein muss . Und das ist der Fall für Zeichenketten, für Listen, für Wörterbücher. Also wenn ich das ausführe,
dann wirst du sehen , dass es kein Problem ist,
diesen Code auszuführen und dann
einfach
auszudrucken , was ich ausdrucken
wollte. Was also passiert, sind
Wörterbücher, Listen und Zeichenketten. Natürlich sind es sehr unterschiedliche
Arten von Objekten, oder? Aber Duck Typing akzeptiert sie als Teil der Argumente
der Längenfunktion weil das einzige, was hier benötigt
wird oder worauf
zugegriffen wird , die Length
Dunder Methoden sind. Solange das also
ihre Enteneingabe ist
und Python startklar ist und das akzeptiert, obwohl diese Typen
strukturell nicht exakt übereinstimmen weil eine Zeichenfolge keine
Liste ist und die Liste
nicht das Wörterbuch ist. Aber in einer Ente
funktioniert das Tippsystem ohne Probleme. Sie können diesen
Schritt sogar noch weiter gehen, z. B. hier, wenn das Klassenbuch
, das keine Initialisierer hat
, ein Autor, ein
Titel und Seiten ist. Und ich habe hier die
Längenmethode selbst definiert, und das gibt nur
die Anzahl der Seiten zurück. Und dann drucke ich, indem ich
die Längenfunktion
für ein Buchobjekt aufrufe . Das ist es, was du hier siehst. Und dann
siehst du hier, wenn ich das ausführe, bekommst
du das als Ergebnis. In diesem Fall
funktioniert es also genauso. Das einzige, was
die Längenfunktion benötigt, ist ein Objekt der Typgröße. Und das bedeutet, dass
es
eine Lean-Donor-Methode geben sollte , was in
dieser Klasse zur Hälfte der Fall ist. Dann läuft dieser Code also
problemlos , denn so
funktioniert Duck Typing.
3. Typ Anmerkungen 2/3: Mit Python und Sie müssen
keine Typen
explizit angeben ,
wenn Sie ein Ziel schreiben. Es ist jedoch eine gute Idee,
dies zu tun, da es Ihnen helfen wird Ihren Code leichter lesbar zu
machen. Und das ist
eigentlich ganz einfach. Zum Beispiel haben wir hier eine
Zeichenfolge, die HelloWorld heißt, aber Sie können tatsächlich
mithilfe eines Typhinweises oder
einer Art von Notation angeben , was der Typ dieser
bestimmten Variablen ist. Und das machst du einfach,
indem du eine Spalte schreibst und dann den Typ
tippst, du tippst den Typ genau hier ein. Wir können das Gleiche tun. Das ist also eine Liste von ganzen Zahlen. Also werde ich
eine Liste mit ganzen Zahlen schreiben. Und wenn Sie einen
generischen Typ wie diesen haben, können
Sie
die eckigen Klammern verwenden,
um mit der rechten Maustaste auf den Text dahinter zu klicken. Und für das Wörterbuch ist
das sehr ähnlich. Wir haben also ein Diktat und das erste, der Schlüsseltyp ist eine Zeichenfolge, oder? Wir haben 12.3, das sind Zeichenketten und was es auf den
Wert zeigt, ist eine Ganzzahl. Hier haben wir
übrigens den
Wörterbuchtyp, um diesen Typ zu
verwenden. Und ich sage dir, du
brauchst Python 3.9 oder neuer. Andernfalls müssen Sie
mit Eingabe von import
schreiben, mit einem Großbuchstaben
diktieren, und dann können Sie das verwenden. Wenn Sie jedoch eine aktuelle
Version von Python verwenden, können Sie
dies einfach schreiben. Es ist viel schneller. So
spezifizieren Sie also Typen. Natürlich ist Klasse auch ein Typ. Ich kann so etwas schreiben, sei ein Untertypbuch. Und das wird ein Buch sein. Und dann können wir
ihm einige Werte übergeben. So etwas. So fügen Sie
Typhinweise hinzu , wenn Sie Variablen
deklarieren. Nun, das ist nicht so nützlich, denn wenn Sie
sich die Codezeile ansehen, können
Sie bereits sehen,
dass es sich um ein Buch handelt. Also warum sollten wir
das schreiben müssen, oder? Es ist nicht wirklich notwendig, aber das ist wirklich
nützlich, wenn Sie Funktionen oder Methoden
haben und
Typhinweise für Argumente angeben möchten. Das ist eigentlich das, was
du hier siehst. Wir sehen also, dass wir einen
Autor vom Typ String haben. Wir haben einen Titel vom
Typ String und wir haben Seiten vom Typ Integer. Das ist wirklich nützlich
, denn wenn wir hier
den Buchinitialisierer aufrufen , können
Sie sehen, dass ich in diesem Fall
VS-Code verwende. Ich erhalte also bereits die Typinformation
in der Kopfzeile. Jetzt weiß ich genau,
was ich bereitstellen muss. Dieser Autor
soll eine Zeichenfolge sein und Vital
soll ebenfalls eine Zeichenfolge sein. Und Seiten und Innenraum. Sie werden das hier
als Rückgabetyp sehen. Der Buchinitialisierer
gibt also nichts zurück,
und das ist richtig. Hier gibt es keine
Rückgabeerklärung. Du kannst das auch
explizit schreiben , wenn du es
willst, so. Es gibt also keine und Länge zurück. Wenn Sie sich das ansehen,
wird eine Ganzzahl zurückgegeben. Wir können das also auch
explizit spezifizieren. Eine Sache,
über die Sie sich vielleicht wundern, ist, was passiert wenn wir den
Typ falsch angeben, z. B. haben wir
hier eine Variable
vom Typ string, oder? Und wir weisen die Zeichenfolge zu, das ist
also alles korrekt. Aber was passiert, wenn ich
das in eine Ganzzahl umwandle, zB das ist eindeutig keine
Ganzzahl, oder? Wenn wir das also ausführen, sehen
Sie, dass der Code tatsächlich völlig
problemlos
läuft, obwohl der Typ völlig falsch
ist. Und das ist der Grund, warum Python
diese Typen
nicht betrachtet , wenn es das Programm
tatsächlich ausführt. Sie sind wirklich nur dazu
da, uns als
Entwicklern zu helfen , zu verstehen,
wo die Probleme in unserem Programm
liegen Sie sehen, wir erhalten hier nicht einmal
eine Fehlermeldung und hier
können uns die VS-Code-Einstellungen helfen festzulegen, wie streng
unser
Typprüfsystem in
unserer IDE offen sein soll. Jetzt sehen die Einstellungen
für den Arbeitsbereich in VS Code und Dairy, dass es
einen Python-Punkt-Analysis-Punkttyp gibt , der die Form
überprüft, die deaktiviert ist. Sie können diesen Wert also ändern, um zu
bestimmen, wie streng die
Typprüfung sein soll. Und es gibt im Grunde
drei Optionen. Es gibt Off Basic und Strikter. Lassen Sie mich das also auf streng ändern. So. Gehen wir jetzt zurück zu meiner
Akte und wagen es, zu sehen, hey, jetzt haben
wir ein Problem. Siehst du, meine Zeichenfolge
ist eine Ganzzahl, aber wir weisen ihr eine Zeichenfolge zu. Und Sie sehen auch, dass wir
einen Inkompatibilitätsfehler erhalten , der von Piloten bereitgestellt handelt es sich um die
Python-Sprachoberfläche von VSCode. Also lass mich das
wieder in eine Zeichenfolge ändern oder du wirst es übrigens
auch hier sehen. Das ist meine Zeichenfolge ist eine Ganzzahl. Ich sehe, dass wir hier
auch das Problem , dass int
zugewiesen werden kann, weil es nicht vom Typ size in abweicht und
keine Length Dunder Methode hat. Lassen Sie uns das also wieder in eine
Zeichenfolge ändern und dann werden wir sehen
, dass das Problem gelöst wurde.
4. Duck mit Protocol: Ein ziemlich Python-spezifischer Typ ,
über den ich mit Ihnen sprechen möchte, und das ist die Protokollklasse. Wir haben also
im anderen Beispiel gesehen , dass
wir Unterricht haben können. Und die Klasse ist
natürlich ein Typ. Aber was oft passiert,
ist, dass Sie überall
in Ihrem Code
Klassen und Objekte
eines bestimmten Typs verwenden Klassen und Objekte
eines , oder? Hier habe ich ein Beispiel dafür
, in dem wir
eine Klasse namens
E-Mail-Clients haben , oder
sagen wir , dies ist ein
E-Mail-Versandsystem. Und Sie sehen, was
hier passiert , ist, dass wir
den Initialisierer
haben der eine Reihe von
Informationen wie Logins, Passwörter usw. abruft. Aber innerhalb des Initialisierers erstellen
wir einen SMTP-Server. Wir haben dann versucht, den
Host und den Port aus
dem SMTP-Serverobjekt abzurufen
, das wir gerade erstellt haben. Und dann
überprüfen wir
einige Dinge wie den Benutzernamen und ein Passwort und speichern diese beiden Adressen
und so weiter und so weiter. Und dann haben wir ein
paar Methoden wie eine Verbindung zum Server herstellen, den Server verlassen
und eine Nachricht
senden, eine E-Mail über diesen
Surfer senden mit einigen hilfreichen Dingen wie dem systematischen
Hinzufügen der beiden Adressen und solche Dinge. Wir haben hier also viele Typen. Sie sehen, dass wir hier
die Rückgabetypen haben , die meistens nicht der Fall sind. Wir verwenden
hier auch andere Arten von Typanmerkungen wie diese, z. B.
bedeutet das, dass die Anmeldung
eine Zeichenfolge sein kann oder dass sie bekannt sein kann. Dies wird also auch als Union-Type-Syntax bezeichnet
. Das bedeutet, dass Sie
mehrere Typen kombinieren können und
einem Standardtyp oder
weisen wir ihm den Wert none zu . Sie sehen auch, dass wir uns
hier auf den SMTP-Typ verlassen
, der aus der
SMTP-Bibliothek stammt, oder? Und das ist an sich kein
Problem, aber es bedeutet, dass es
keine Abhängigkeit zwischen Ihren E-Mail-Clients und einer
ganz bestimmten SMTP-Klasse gibt. Wenn Sie dafür
eine Bibliothek verwenden möchten, müssten Sie in
die Klassenimplementierung gehen und die Verweise auf SMTP
korrigieren
und dann diesen Import entfernen. Eine andere Möglichkeit, dies zu tun,
ist die Verwendung von Protokollen. Und mit dem Protokoll ist das,
was Sie tun eine wirklich nette Erweiterung
des Duck-Typing-Mechanismus. In Python mit Protokoll geben
Sie an, wie die Struktur des Objekts aussehen soll. Das ist also der strukturelle Teil des Duck-Typings und das, was Sie erwarten. Und dann
wird Pythons
Duck-Typing-System das zur Laufzeit abgleichen. Ich habe hier also ein anderes
Beispiel, in dem ich diesen Mechanismus verwendet habe. Und das ist
genau dieselbe Klasse. Also wir haben hier wieder
den E-Mail-Client, aber jetzt siehst du, dass es
eine weitere Klasse gibt, die darüber
geschrieben ist und Where are we? E-Mail-Server? Ein E-Mail-Server ist
eine Protokollklasse. Sie sehen, dass wir das vom Tippen
importiert haben. Und dann gibt es
hier ein paar Eigenschaften und Methoden, die ich definiert habe. Es gibt also den Host und die
Pfeile zum Verbinden der Methoden. Das sind also die
Standardmethoden, die auch den Kern
der B-Serverklasse ausmachen. Aber jetzt geben wir eine
Instanz dieses SMTP-Servers an die E-Mail-Clients weiter, und dann verwenden wir ihn einfach. Und das Schöne ist
, dass wir, weil wir das
Protokoll jetzt einfach als Typ bereitstellen, den SMTP-Server
wie zuvor verwenden können. Wir müssen es einfach
außerhalb des E-Mail-Clients erstellen. Das nennt man übrigens
Dependency Injection. Und wenn wir
es durch etwas anderes ersetzen wollen, z. B. wollen
wir
einen anderen SMTP-Server verwenden oder vielleicht wollen wir
einen gefälschten SMTP-Server verwenden , damit wir einige
Softwaretests für diese Klasse schreiben
können. Nun, dann können wir das
einfach bereitstellen. Und solange die
Klasse, die wir bereitstellen, das Objekt, das
bereitstellen wird, diesem Protokoll. Solange es diese Methoden
hat und Doctype das abgleicht
, können wir es in
Kombination mit dem E-Mail-Client verwenden. Und wir haben hier auch den sehr
spezifischen Import
aus der SMTP-Lib verloren , weil
wir uns jetzt einfach
auf ein Protokoll verlassen. Das Protokoll ermöglicht es Ihnen also, eine gewisse Abstraktion in
Ihren Code
einzuführen , sodass Sie sich nicht zu viele
Gedanken über viele,
viele Kopplungen,
viele, viele
direkte Abhängigkeiten
von Low-Level-Bibliotheken, enge Hosen wie ich
Ihnen gerade gezeigt habe , eine wirklich hilfreiche
Methode zur Verbesserung der Lesbarkeit
Ihres Codes machen müssen, die
nützlich sein kann , wenn Sie mit einem Team
zusammenarbeiten über diesen Code oder wenn Sie den Code
schreiben und dann ein
paar Monate später zu ihm
zurückkehren und versuchen herauszufinden, was vor sich geht und was Sie
als Argumente an eine
Funktion oder so übergeben sollen . Tipphinweise sind sehr
hilfreich, um das zu verdeutlichen und sicherzustellen, dass Sie als Entwickler weniger
Fehler machen. ZB hier ist eine
Funktion
, die Statistiken berechnet und einige Argumente erhält. Wir haben eigentlich keine Ahnung, wenn man sich die
behandelten Funktionsstörungen ansieht , was wir damit machen
sollen Es gibt Anwender,
Pflanzen und Produkte, aber was sind diese Dinge? Handelt es sich um Wörterbücher
oder um Listen? Ist es eine Zelle für eine Zahl? Wir wissen es einfach nicht. Wenn Sie Tipphinweise angeben. Das ist viel einfacher zu sehen. Wir können sofort sehen, was
wir liefern müssen und Typprüfer
in VSCode-Pylonen
eingebaut sind. Aber auch andere Editoren haben
einen solchen Typprüfer. Es hilft Ihnen zu verstehen
, wo sich die Pfeile befinden, und sie
zu
lösen, bevor Sie Ihr Programm
überhaupt ausführen müssen , um das herauszufinden. Typen helfen also bei
der Lesbarkeit Ihres Codes und sie
helfen Ihnen auch dabei, Fehler zu einem früheren Zeitpunkt
im Entwicklungsprozess zu erkennen.
Indische Handschriften werden Ihnen viel Zeit sparen. Ich empfehle
Ihnen daher dringend,
sie häufiger zu verwenden , falls Sie das noch nicht
getan haben. Damit ist diese
Lektion über Tipphinweise abgeschlossen. In der nächsten Lektion werde ich mich eingehender mit den Klassen befassen und Ihnen ein paar
sehr leistungsstarke Dinge
zeigen, die Sie mit ihnen in Python machen können.
5. Nächste Stufe Kurse 1/4: In dieser Lektion
werde ich über
Klassen sprechen und Ihnen
ein paar verschiedene Dinge zeigen , die Sie mit ihnen in Python machen
können. Ich habe hier also ein sehr
einfaches Beispiel. Es ist Klasse Person,
nichts Besonderes. Fast leeres Glas
hat nur einen Initialisierer und es bekommt einen Namen
und eine Adresse. Wie Sie sehen können, sind es Schnüre. Ich verwende hier Typhinweise. Ich sollte wahrscheinlich hinzufügen, da der Initialisierer nichts
zurückgibt. Und dann verwende ich eine
Generate-ID-Funktion. Sie können diese
Funktion
hier sehen, um eine
Art von ID zu generieren. Sie könnten sich das also
wie eine vereinfachte Datenbank vorstellen . Und dann haben wir einen
Namen und eine Adresse, und wir haben auch eine Liste, leere Liste von E-Mail-Adressen. Das ist also die
Personenklasse Basic. Und dann habe ich die
Hauptfunktion, in der ich
eine Person mit einem Namen
und einer Adresse erstelle eine Person mit einem Namen
und einer Adresse und dann diese Person ausdrucke. Also, wenn ich diesen Code fertig
ausführe, werden wir das
zu Ergebnissen bringen. Also drucke ich ein Personenobjekt. kannst du
hier sehen. Nun, das sind keine sehr nützlichen
Informationen, oder? Weil wir einfach eine Speicheradresse
bekommen. Wir haben keine Ahnung, was
tatsächlich
im Person-Objekt enthalten ist. Es wäre schön, wenn wir das
tatsächlich sehen könnten. Und das ist natürlich in Python
möglich. Dies
können Sie hauptsächlich tun,
indem Sie eine STR- oder
Wrapper-Dunder-Methode hinzufügen. Ich werde in einer Minute mehr
darüber sprechen. Insgesamt gibt es in Python jedoch
eine andere
Art , Klassen zu definieren. Das ist insgesamt etwas einfacher. Ich fühle mich etwas einfacher zu lesen und das liegt daran, dass ich Datenklassen
verwende. Aber man könnte sagen, dass
Datenklassen wirklich eher auf
datenorientierte Klassen ausgerichtet sind , oder? Strukturierte Datenpunkte und
Vektoren und solche Dinge. Anstelle einer Schaltfläche oder einer Pflasteroberfläche oder einer
anderen verhaltensorientierten Klasse. Es fügt jedoch viele
praktische Mechanismen hinzu, z.
B. eine viel einfachere Methode
zum Definieren von Attributen. Sie können sie
viel einfacher vergleichen. Sie können sie
viel einfacher ausdrucken. Diese Dinge sind also
für fast jede Art von Unterricht nützlich. Wie machen wir eine Person
zur Datenklasse? Das ist eigentlich ganz einfach. Was ich also tun werde,
ist aus Datenklassen Datenklasse zu importieren
, den Typ, den
wir hier verwenden werden. Und dann, anstatt
eine Person auf diese Weise zu definieren, werden
wir eine darüber
liegende Datenklasse schreiben. Und jetzt kann ich
die
Instanzvariablen genau hier angeben . Wir haben also einen Namen
, der eine Zeichenfolge ist, und wir haben eine Adresse, die ebenfalls Spring ist. Und wir werden eine
Liste mit E-Mail-Adressen haben. Das ist eine Liste von Zeichenketten, oder? Und der Ausweis. können wir auch, ich zeige Ihnen in einer Minute,
wie das geht. Aber wenn ich das jetzt entferne, können
Sie sehen, dass
es viel einfacher ist zu verstehen, was eine
Person eigentlich ist weil wir einfach nach oben schauen können und wir sofort
die
Namen
der Instanzvariablen und ihre Typen sehen . Und deshalb sind
Datenklassen wirklich nützlich. Und darauf komme ich in einer Minute zurück
. Lassen Sie mich das einfach kommentieren. Aber wenn ich jetzt auf diese Weise
persönlich etwas erstelle, passiert
das
genauso. Datenklassen generieren also
tatsächlich einen Initialisierer,
der auf den Werten dieser
Instanzvariablen basiert . Wenn ich das ausführe, können Sie sehen , dass es jetzt die Person druckt. Aber Sie sehen auch,
dass diese Datenklasse bereits gelöst hat, dass, wenn Sie das Objekt
drucken, etwas Sinnvolles drucken wird , und das tut sie, indem sie
die Wrapper-Dunder-Methoden implementiert . Darüber werde ich
in einer Minute auch mehr sprechen. Wie fügen wir diese
anderen Dinge zur Datenklasse hinzu? Natürlich haben wir die
ID, die eine Zeichenfolge ist, aber jetzt möchten wir ihr
einen Wert zuweisen , der
von dieser Funktion generiert wird. Um das zu tun, müssen
wir also die Feldfunktion verwenden , die
auch in Datenklassen enthalten ist. Und was ich hier mache,
ist, dass die ID dem Feld entspricht und die Standardfabrik, das ist im Grunde die
Funktion,
die den Wert für uns erstellt , ist
die generierte ID. Was nun passiert
, ist , dass
die Datenklasse, um diesen Wert zu
berechnen die Datenklasse, um diesen Wert zu diese Funktion
aufruft,
um ihn zu berechnen. Und weil dies jetzt einen Standardwert
hat, müssen
wir ihn darunter angeben. Die anderen Zellen
haben keinen Standardwert. Da haben wir es also. Wenn ich das jetzt erneut ausführe, werden
Sie sehen, dass meine
Person jetzt einen Namen und eine Adresse hat, aber jetzt hat sie auch
eine ID, die durch
den Aufruf der Funktion Generate ID generiert
wurde. Sie können auch einfach
einen Standardwert angeben, z. B. nehmen wir an, wir haben
hier eine
aktive Instanzvariable , die ein boolescher Wert ist. Und standardmäßig wird
das auf True gesetzt. Jetzt ist eine Person
standardmäßig aktiv. Und Sie sehen, dass es jetzt auch hier im
Objekt Person
enthalten ist. Was können wir jetzt noch tun? Nun, wir haben die
E-Mail-Adressen auch hier aufgeführt, also fügen wir das auch hinzu. Und dann fügen wir hier auch
einen Standardwert hinzu. Jetzt könnten Sie
versucht sein, dies zu schreiben. Das ist keine gute Idee, denn Python
funktioniert so, dass dieser Wert tatsächlich einmal
zur Interpret-Zeit generiert wird. Wenn Sie es also
als Standardwert zuweisen und
das ist der gleiche Grund warum Sie in Funktionen keine leere Liste
als Standardwert
zuweisen sollten . kann zu
unerwartetem Verhalten kommen, da all diese leeren Listen
im Grunde auf dasselbe Objekt
verweisen
und das möchten Sie nicht. Was Sie also tun können, ist
hier
auch ein Feld zu definieren und einfach zu sagen,
dass der Standardwert ,
diese Standardfabrik,
der Listeninitialisierer sein wird , so. Jetzt wird jede Person
auch
eine Liste von E-Mail-Adressen haben , die standardmäßig leer ist. Andere Dinge, die Sie mit
Datenklassen machen können , die wirklich nett
sind. Nun, zum einen generiert
es, wie wir gesehen haben, den Initialisierer. Also hier haben wir eine Person. Es hat also einen Namen, eine Adresse, ID, eine aktive und eine Liste
von E-Mail-Adressen. Aber vielleicht
möchten Sie nicht, dass die ID da ist, Sie möchten, dass sie
immer generiert wird. Was Sinn macht, oder? Wir wussten es nicht, wir wollen diese IDs nicht explizit
angeben. Wir möchten, dass es automatisch
generiert wird. Was Sie also tun können, ist
,
dem Feld einfach eine Funktion zu geben, in der es
gleich falsch ist, also so. Und wenn Sie sich jetzt noch einmal die Definition
von Denise lives ansehen, sehen
Sie, dass das ID-Feld nicht
mehr Teil
des Initialisierers ist , aber es ist natürlich immer noch
Teil der Person, die wir
hier sehen, die automatisch
generiert wird. Auf diese Weise können Sie
eine gewisse Kontrolle
darüber haben , wie der Initialisierer aussehen
wird und gleichzeitig diesen
wirklich schönen
Überblick über alle
Instanzattribute haben . Eine andere Sache, die Sie
vielleicht tun möchten, ist , dass wir dieser Person eine
Suchzeichenfolge hinzufügen möchten. Nehmen wir an, wir haben
eine Suchzeichenfolge. Instanzvariable,
ja, das ist eine Zeichenfolge. Und was wir jetzt wollen
, ist, dass der Wert hier aus dem Namen
und der Adresse
abgeleitet wird . Das
wollen wir also können, Sergio. Aber natürlich
können wir diesen Wert hier
noch festlegen, weil wir diese Werte nicht
haben. Dies ist einfach eine Spezifikation
der Instanzattribute. Was wir
stattdessen tun können, ist, einfach ein Feld
anzugeben und
es auf gleich falsch zu setzen , weil wir nicht als
Teil des Initialisierers angeben können wollen die Suchzeichenfolge
nicht als
Teil des Initialisierers angeben können wollen. Aber was wir dann tun können,
ist, einen Schub zu definieren. Dunder-Methoden geben keine
ihrer eigenen
Punktsuchzeichenfolgen zurück , die dem gleichen Wert entsprechen. Und dann
konstruieren wir einfach die Zeichenfolge self.name und self dot address so. Was nun passiert ist
, dass beide Eingaben aufgerufen werden, nachdem das Objekt erstellt
wurde. haben wir also den
Namen und den Adresswert und dann können wir
die Suchzeichenfolge berechnen. Wenn ich diesen Code erneut ausführe, sehen
Sie, dass wir jetzt
all diese Werte hier haben,
aber wir sehen auch, dass wir
eine Quellzeichenfolge haben, die aus
dem Namen plus Leerzeichen
und dann der Adresse besteht . Was können wir also noch tun? Nun, vielleicht wollen wir nicht, dass die Suchzeichenfolge
erscheint,
wenn wir die
Person drucken, weil das
eine Art doppelte
Entzündung ist , oder? Sie können sich vorstellen, dass, wenn
die Personenklasse wächst, diese Suchzeichenfolge sehr lang wird
. Anstatt es auszudrucken, können wir
jedes Mal, wenn wir Person drucken, auch hier hinzufügen, dass ein
Rapper gleich falsch ist. Und das bedeutet einfach, dass,
wenn wir die Person drucken Suchzeichenfolge nicht
Teil der Darstellung sein wird . Es wird nicht enthalten sein.
Das siehst du hier. Und zur Verdeutlichung: Diese
Suchzeichenfolge ist eigentlich etwas
Klasseninternes. Sie können sich auch dafür entscheiden,
einen Unterstrich
davor zu setzen , so. Und jetzt machen wir diese
Unterscheidung in der
Klassendefinition selbst noch klarer. Wir können auch
kontrollieren, wie Objekte erstellt werden. Also hier haben wir eine Person, wir geben einen Namen und eine Adresse an, aber wenn Sie möchten, können
wir diese Argumente entfernen, Schlüsselwortnamen hier und jetzt funktioniert
das natürlich trotzdem. So funktionieren Klassen in Python
standardmäßig, oder? Was aber, wenn Sie
sicherstellen möchten, dass Sie es
nur mit
Schlüsselwortargumenten angeben können es
nur mit
Schlüsselwortargumenten angeben , die
Sie immer schreiben müssen, Name ist gleich und Adresse ist gleich. Nun, das können Sie tun, indem Sie hier
ein Argument an den Decorator der
Datumsklasse übergeben , und das ist
nur das Schlüsselwort und die Standardeinstellung, das ist falsch, aber wir
können es auf wahr setzen. Und jetzt sehen wir hier, dass
wir tatsächlich
eine Fehlermeldung erhalten , weil Keywords
erwartet werden. Jetzt müssen wir schreiben, dass der
Name gleich John ist und die Adresse entspricht
123 Hauptstraßen. Damit das funktioniert, hat das keinen Effekt was der tatsächliche Output ist, sondern es beeinflusst, wie wir Personen erschaffen
können. Und diese zusätzliche Strenge
kann manchmal ein hilfreiches Werkzeug sein. Sie können auch eine Datenklasse einfrieren
lassen. Und das bedeutet, dass Sie das Objekt
ändern können , nachdem
es erstellt wurde. Und das tun wir, indem wir die
Tiefkühlprodukte so liefern . Aber jetzt passiert etwas
Interessantes. Sie sehen, dass unsere Idee mit der Suchzeichenfolge
eigentlich nicht mehr funktioniert, weil wir
hier natürlich ein eingefrorenes Objekt haben, was bedeutet, dass wir es ändern können, aber wir ändern
es immer noch, nachdem es erstellt wurde. Ich werde
Ihnen in einer Minute einen anderen
Weg zeigen , wie Sie das angehen können. das vorerst Lassen Sie mich das vorerst einfach löschen. Wir werden später etwas
anderes verwenden , um
dieses Problem zu lösen. Also, wenn ich das jetzt starte, funktioniert es
natürlich immer noch, aber jetzt, wenn ich versuche, die Person zu
ändern, Punktname der
Person gleich, jetzt siehst du, dass wir das eigentlich
nicht tun dürfen. Die Person ist eingefroren und es wird eine
Fehlermeldung angezeigt, wenn Sie dies ausführen.
Sie sehen auch, dass wir einen Fehler mit einer
eingefrorenen Instanz erhalten. Das ist sehr hilfreich,
wenn Sie
sicherstellen möchten ,
dass Sie bei der
Verwendung einiger Daten die Daten nicht versehentlich
ändern. Aber wie lösen wir dieses Problem mit der
Suchzeichenfolge jetzt, da wir dieses Objekt nicht
ändern dürfen , nachdem
es erstellt wurde. Nun, eine Sache, die Sie tun können,
ist stattdessen Eigenschaften zu verwenden.
6. Nächste Stufe Kurse 2/4: Dies ist eine weitere sehr
interessante Ergänzung zu den Klassen, mit denen Sie sie viel mächtiger
machen können. Was Sie tun können, ist,
anstatt dies zu verwenden, tatsächlich eine Eigenschaft verwenden,
um einen Suchbegriff zu definieren. Also werde ich hier
ein Grundstück haben und nennen wir das
Top T-Shirt String. Es ist fast wie eine Methode. Und das wird eine Zeichenfolge zurückgeben. Und ich werde das einfach hier
entfernen. Und die Suchzeichenfolge
wird
eine
F-Zeichenfolge sein , die self.name, self.age, address usw. enthält. Es ist also immer noch gefroren. Aber lassen Sie uns das
jetzt wieder entfernen. Wenn ich die Person drucke. Nun, die Suchzeichenfolge ist wegen der Eigenschaft nicht
da, aber wir haben sie, sodass ich Personenpunkt,
Suchzeichenfolge usw. drucken
kann . Es beschwert sich, dass das jetzt ein privates Mitglied
ist, aber wie Sie sehen, funktioniert
es tatsächlich in seinen Drucken. Sicher, wenn Sie möchten Suchbegriff
öffentlich verfügbar ist, können
Sie natürlich diese Seite verwenden, um diesen Unterstrich so zu entfernen. Und jetzt ist der Pylonenfehler
auch um uns herum wieder vorbei, wir bekommen immer noch die gleichen Ergebnisse. Sobald wir also hier
eine schreibgeschützte Eigenschaft hinzugefügt haben , die
auch als Getter bezeichnet wird. Und es ist nur lesbar, weil wir ihm nichts zuordnen
können. Wenn ich sage, dass die
Suchzeichenfolge für Personen gleich hoch ist, dann sehen Sie, dass wir hier die
Fehlermeldung erhalten, dass wir kein Mitglied einer
Eigenschaft
zuweisen können , die nicht zulässig ist. Was Sie tun können, wenn
die Suchzeichenfolge
änderbar sein soll , ist,
tatsächlich einen Setter hinzuzufügen. Und da Quelle z.B. Eigentum ist, ist das in Python
wirklich einfach. Wir schreiben einfach die
Suchzeichenfolge Punkt und dann haben wir
hier den Punktesetzer. Und dann definieren wir einfach noch einmal den
gleichen Eigenschaftsnamen. Aber es akzeptiert ein Argument
, das der Wert ist. In diesem Fall ist das eine Zeichenfolge. Es wird Null zurückgeben. Und dann
können wir hier den Wert festlegen. Jetzt wird das natürlich
nicht funktionieren weil unsere Datenklassen eingefroren sind, richtig, also können wir alles
ändern. Also, wenn wir das entfernen und wir
jetzt Dinge speichern können. Und wie Sie
einen Wert im Objekt speichern könnten ,
wenn Sie möchten. Aber das
brauchen wir im Fall
der Quellzeichenfolge natürlich nicht wirklich ,
weil wir hier einfach einen berechneten Wert
zurückgeben.
Ich habe hier
ein anderes Beispiel
, das in
Bezug auf die Eigenschaft etwas sinnvoller ist. Ich habe also einen Klassenvideoclip Minuten und
Sekunden, einem Titel. Und Sie sehen, wir sind eine
Eigenschaft namens Dauer. Und im Grunde ergibt sich,
abhängig von der Anzahl der
Minuten und
der Anzahl der Sekunden,
insgesamt Sekunden. Und dann können wir
auch einen Setter haben , der eine Anzahl von Sekunden festlegt. Und das verwendet im Grunde
die Funktion div mod, um zu berechnen, wie hoch der Minuten- und
Sekundenwert sein soll. Hier sehen Sie also ein Beispiel für
die Verwendung einer Eigenschaft, eines Getters und eines Setters, um zu steuern, wie Werte gespeichert
werden. Objekt, in diesem Fall Minuten und Sekunden
des Videoclips. Und hier haben wir ein
Videoprojekt mit einer Liste von Videoclips. Und wieder ist das ein Feld, das als Standard-Fabrikliste
verwendet wird. Wir haben einen
Standardwert für unseren Titel und dann haben wir auch eine
Eigenschaft für die Gesamtlänge, und das ist die Summe der
einzelnen Clips, die Anzahl der
Minuten und Sekunden. Dann habe ich eine einfache Hauptfunktion, bei der
ich zwei Clips habe. Einer ein Videoclip von
einer Minute und 30 s,
ein weiterer Videoclip
von 2 Minuten und 30 s. Und dann erstelle ich ein Projekt
, das diese beiden Clips enthält. Ich drucke die Gesamtlänge aus, aber dann verwende ich den Duration Setter, um die Länge des Clips zu
ändern, Dauer 220 s, was
eigentlich 2 Minuten sind. Und dann können wir die Gesamtlänge des
Projekts drucken. Und wenn ich das dann
starte, dann bekommen wir das. Also bekommen wir 240, aber dann
gehen wir von 1 Minute auf 2 Minuten. Das sind also dreißig Sekunden mehr. Das sind also 270 s
, die gedruckt werden. Oder Sie können auch sehen, dass,
wenn ich den Clip hier drucke, Friends einen Clip ausschneiden und ich diesen Code erneut
ausführe. Sie sehen, dass wir nach der
Aktualisierung des Clips 2 Minuten und 0 s
haben. Und genau das ist
unsere Dauer cetera Dosis. Und wenn Sie sich ein Videoprojekt
ansehen, können
wir das sogar noch
weiter
vereinfachen , denn hier sind
Eclipse-Punktminuten,
Blöcke, Clip-Punktsekunden. Nun, wir können
die Dauer, die sie hierher gebracht hat, einfach nutzen , um es noch kürzer zu machen. Und dann werden wir
genau das gleiche
Ergebnis wie zuvor erzielen . Das sind also Eigenschaften, die hilfreich sein
können, um
einen berechneten Wert zu erhalten , ohne diesen Wert
tatsächlich
speichern zu müssen. Und sie helfen Ihnen auch dabei,
einige Daten auf niedriger Ebene in
einer Klasse zu verstecken einige Daten auf niedriger Ebene in , z. B. wenn Sie intern
Minuten und Sekunden haben, aber Sie einfach
Sekunden extern erledigen Ein Property Getter und Setter hilft
Ihnen dabei, das zu erreichen.
7. Nächste Stufe Klassen 3/4: Zwei weitere Dinge, über die ich sprechen
möchte, bevor ich diese Lektion beende. Eins ist String versus Wrapper. Wir haben also gesehen, dass, wenn Sie
eine Datenklasse wie
diese Personenklasse haben und wir die Person ausdrucken, die
wir sehen, dass wir eine Art
entwicklerfreundliche Version dessen erhalten ,
was die Person tatsächlich ist , die beim Debuggen hilfreich oder wenn Sie
etwas sperren möchten oder was auch immer. Und genau das soll der
Wrapper tun. Wrapper soll Ihnen eine entwicklerfreundliche
Darstellung eines Objekts geben. Die Idee ist sogar
, dass Sie in der
Lage sein sollten , diese Darstellung in einer Datei zu
speichern und sie sollte genügend
Informationen
enthalten, um sie später aus
einer Datei erneut zu lesen und das Objekt neu zu erstellen
, das
sich einer Datei erneut zu lesen und das Objekt neu zu erstellen von einer benutzerfreundlichen
Darstellung unterscheidet . Dies ist nicht etwas
, das ein Benutzer
sehen soll , da es ziemlich schwer
zu lesen und zu schreiben ist. Und hier ist die Methode vier, bei der die Zeichenfolge
dominiert wird. Wenn Sie also auch
eine benutzerfreundlichere
Darstellung eines Objekts haben möchten , können
Sie tatsächlich die
String Dunder Methoden verwenden. Die Datenklasse fügt dies nicht hinzu, aber Sie können es selbst hinzufügen indem Sie
einfach die
String-Dunder-Methoden hinzufügen. Und das wird
natürlich eine Zeichenfolge zurückgeben, oder? Und was wollen wir zurückgeben? Nehmen
wir an, wir möchten einfach den Namen der Person
drucken. Also das ist ein
selbstgemachter Punktname, so. Wenn wir
dieses Programm jetzt erneut ausführen, sehen
Sie, dass es jetzt einfach den Namen
ausdruckt. Und das liegt daran, dass String
Dunder den Rapper überschreibt, oder? Wenn Sie also keinen String,
aber einen Rapper haben, wird
Python den Wrapper verwenden. Wenn du eine Zeichenfolge hast, wird sie stattdessen diese
verwenden. Aber was ist, wenn Sie immer noch die
Wrapper-Version der Person
drucken möchten? Nun, es gibt ein paar
Möglichkeiten, dies zu tun. Zum einen können Sie die
Wrapper-Funktion so verwenden. Und das wird einfach
die
Wrapper-Dunder-Methode aufrufen und das dann als Zeichenfolge
zurückgeben
, die wir jetzt drucken können. Also, wenn ich dieses Gänseblümchen mache, bekommen
wir unsere Person, eine
entwicklerfreundliche Person. Auch hier können Sie F-Zeichenketten verwenden. Also, wenn Sie eine solche
F-Zeichenfolge haben und jetzt natürlich einfach die Person
drucken. Also nochmal, das wird
die String-Dunder-Methode drucken, aber Sie können tatsächlich das Ausrufezeichen R
verwenden Und in einer F-Zeichenfolge wird
damit auch die Wrapper-Version
der Objekte
gedruckt , bei denen Sie eine
gewisse Kontrolle darüber haben , was für
Dinge gedruckt werden, obwohl Sie
vielleicht sowohl die Wrapper
- als auch die String-Dunder-Methode haben .
Das ist gut zu wissen.
8. Nächste Stufe 4/4: Das letzte, was ich Ihnen zeigen
möchte, ist eine einfache Möglichkeit,
den Zugriff auf
Elemente in Ihren Objekten zu beschleunigen. Und das geschieht durch die Verwendung von Slots. Normalerweise verwendet Python
ein Wörterbuch, um
die Werte der
Instanzvariablen eines Objekts zu speichern . Und der Zugriff auf das Wörterbuch ist schnell, aber nicht unglaublich schnell. Und der Grund, warum es nicht so
schnell ist, ist, dass es
ziemlich dynamisch ist. Sie können jederzeit Schlüssel und
Werte hinzufügen. Sie können sich also grundsätzlich jederzeit
dafür entscheiden, das Objekt dynamisch zu ändern und
neue
Instanzvariablen hinzuzufügen . Python ist eine sehr dynamische Sprache. Denken Sie daran, dass Sie bei Spielautomaten mit dem Dolmetscher
übereinstimmen , dass Sie etwas strenger
sein werden. Sie werden einen festen
Satz von Instanzvariablen haben. Und aus diesem Grund kann
Python
Dinge optimieren und viel schneller
auf diese Dinge zugreifen. In den meisten Fällen werden Sie nun
tatsächlich eine feste Anzahl von
Instanzvariablen
haben. Du willst
deine Objekte nicht ständig und
überall wechseln, oder? Es wird ein Chaos werden. Wenn Sie das also tun und viel verwenden, wird das tatsächlich viel schneller sein. Also hier ein sehr einfaches Beispiel , das wiederum Datenklassen verwendet, die es eine Slot-Option gibt. Sie können also, wenn Sie eine Datenklasse
haben, Slots einfach auf true setzen, wie ich es hier mache. Und dann wird es
Slots anstelle des
traditionellen Wörterbuchs verwenden . Ich habe also eine Version
der Personenklasse, nicht viele verwendet, und eine Version der ersten Klasse
, die sie verwendet. Und dann habe ich hier eine Funktion, zu Elite, die eine
Person oder eine Person bekommt, gehe zu Elite, die eine
Person oder eine Person bekommt,
und die legt die Adresse
fest,
liest die Adresse und löscht die Adresse, nur als
eine Art Benchmark. Und dann habe ich die
Hauptfunktion, in ich
einige Personen, die
Slots Person und
die normale Person erstelle . Und dann verwende ich
Time It, um es zu wiederholen, um die
Funktion get set delete für die Person
aufzurufen. Oft, in diesem
Fall 1 Million Mal. Eigentlich nehme ich den
Median davon, um
die durchschnittliche Leistung zu erhalten ,
und werde drucken, wie viel Zeit das ist Ordnung, die
Leistungsverbesserungen. Übrigens, dieses
Ding hier, teilweise. Darüber werde ich in
der nächsten Lektion sprechen. Also bleib dran. Lassen Sie mich das jetzt ausführen, wir
können sehen, was passiert. sehen jetzt, dass,
wenn wir keine Steckplätze
haben all diese Zugriffs-, Lese-, Schreib- und Löschoperationen 0,06 s,
mit Steckplätzen 0,05 s
dauern . Das ist
also
eine
Verbesserung der Leistung um fast 20%, insbesondere wenn Sie
mit vielen Daten zu tun haben, dann
wird das wirklich große Auswirkungen haben, wenn Sie
diese Operationen überall ausführen. Es ist also sehr einfach, setzen Sie Slots
einfach auf true, wenn Sie
Ihre Datenklasse definieren. Jetzt können Sie von
dieser Verbesserung profitieren. Neben den Geschwindigkeitsverbesserungen verbrauchen die Slots
auch etwas weniger Speicher. Es gibt jedoch ein
paar Vorbehalte. Zum einen kann es zu Problemen kommen, wenn Sie
mehrere
Vererbungs-Down-Slots verwenden . Seien Sie also sehr vorsichtig
damit, aber Sie sollten jeden
Fall vorsichtig sein, wenn Sie Mehrfachvererbung
verwenden. Und eine andere Sache ist
, dass Sie sie
dynamisch zählen , um
Instanzvariablen hinzuzufügen oder zu entfernen, zwei Objekte, weil wir mit zwei Objekte, weil wir mit
Slots
etwas strenger waren. Aber ich denke, insgesamt ist das
eigentlich eine gute Sache. Damit ist diese Lektion abgeschlossen, in der ich
Ihnen ein paar
leistungsfähigere Dinge gezeigt habe , die Sie mit Klassen in Python
tun können. In der nächsten Lektion werde
ich
darüber sprechen, was Sie mit Funktionen
machen können. Und ich werde mir auch
einige funktionale Tools in
Python genauer ansehen , um Ihnen dabei zu helfen.
9. Next-Level Funktionen 1/4: In dieser Lektion möchte ich
über Funktionen und einige der leistungsfähigeren Dinge sprechen über Funktionen und einige der ,
die Sie mit Funktionen in Python
machen können , ähnlich wie wir es mit
Klassen und der vorherigen Lektion gemacht haben . Nun, in Python ist im Grunde alles ein Objekt, oder? Wir haben Ganzzahlen, Zeichenketten und
Klassen, aus denen Sie Objekte erstellen
können. Auch eine Funktion ist ein Objekt, sie ist ein Objekt vom Typ double. Und Sie könnten tatsächlich,
wenn Sie
eine Klasse erstellen möchten , die einen
Aufruf von Dunder Methods hat, dann ist diese Klasse auch eine Callback-Klasse, die
sich auch wie eine Funktion verhält. Eigentlich. Ein sehr einfaches Beispiel hier, ich habe eine Kundenklasse, das ist eine Datenklasse. Wenn Sie mit einem Namen,
einem Alter und ihrer
Funktion schlafen , heißt
das hier E-Mail-Werbung, bei der eine Liste von
Kunden abgerufen wird und die für eine Schleife
verwendet wird, um die Kunden zu
durchsuchen und den Kunden zu überprüfen. Wenn das Alter etwa 50 Jahre beträgt, der Kunde
Anspruch auf eine Beförderung. Und wenn der Kunde über 50
Jahre alt ist, der Kunde
Anspruch auf eine Beförderung. Und abhängig von diesem Wert drucken
wir etwas
Anderes auf den Bildschirm. Dann habe ich eine Hauptfunktion
, die eine Liste von
Kunden erstellt und dann
E-Mail-Werbung an
diese Kunden sendet , zumindest die über
50 haben das umgangen, dann bekommen wir das. Es überprüft also jeden Kunden und druckt dann aus,
wo der Kunde berechtigt
ist,
E-Mail-Werbung zu senden oder nicht . Das ist
eine Funktion, die aufgerufen werden kann, die Liste der Kunden
und Rücksendungen erhält, keine. Und das
ist natürlich eine sehr grundlegende Verwendung von Funktionen in Python, oder? Aber da die
Funktion ein Objekt ist, können
Sie tatsächlich viel
mehr Dinge damit machen. Beispielsweise könnten Sie eine Funktion an eine
andere Funktion
übergeben oder sogar
eine Funktion als Ergebnis eine andere
Funktion zurückgeben lassen. Und das machen wir. Das ist,
wenn Sie sogenannte Funktionen höherer
Ordnung verwenden, z. B. hier überprüfen wir,
ob der Kunde für eine Beförderung
berechtigt ist,
wenn der Kunde etwa 50
Jahre alt ist. Aber vielleicht wollen wir
hier
einen komplexeren Check haben einen komplexeren Check , der auch Dinge
des Kunden überprüft. Nun könnten wir natürlich die if-Anweisung
hier mit immer mehr
Komplexität auf die Bedingung
ausdehnen . Es wäre aber auch
schön, wenn
E-Mail-Werbung irgendwie
einen Mechanismus bekommen könnte , um
die Eignung zu überprüfen , indem eine andere Funktion
aufgerufen wird. Und genau das können wir
mit Funktionen höherer Ordnung machen. Was wir also stattdessen tun können, ist, eine Funktion zu
definieren für eine Beförderung in
Frage kommt UND die
Funktion wird einen Kunden gewinnen. Und es wird einen booleschen Wert
zurückgeben. Und dadurch wird einfach zurückgegeben, dass der
Kundenpunkt h über 50 liegt. Wie verwenden wir diese
Funktion hier? Nun, wir können es einfach
nennen, oder? Wir könnten das tun, wenn es für eine Beförderung in
Frage kommt. Kunde, so. Und wenn wir
das und dann was ausführen werden
wir
genau die gleichen Ergebnisse erzielen. Dies gibt uns aber auch immer noch sehr wenig Kontrolle,
da wir jetzt keine Möglichkeit haben, andere Funktionen zu
definieren
und dann dynamisch bestimmen, ob wir Kunden eine E-Mail
senden sollen oder nicht. Es ist immer eine
bestimmte Festplattenfunktion. Anstatt
es hier direkt anzurufen, können
wir es auch als
Argument für
E-Mail-Werbung weitergeben . Nehmen wir also an, wir
haben die Funktion berechtigt
ist
, das richtig zu schreiben. Da
dies eine Funktion ist, erwarten
wir natürlich etwas
vom Typ Ziel, das ist eine Funktion. Und wie spezifizieren wir, welche
Art von Funktionserkrankung? Nun, das sind
die eckigen Klammern und dann verwenden wir ein weiteres Paar eckiger Klammern, um anzugeben, was und dann verwenden wir ein weiteres Paar
eckiger Klammern, um anzugeben, was
die Argumente
dieser Funktion mit den Parametertypen sind. Was dieser Ausdruck also ist ein Kunde und was dieser
zurückgibt, ist boolesch. Und dann
rufen wir die Funktion, die
wir als Parameter
übergeben, nicht
direkt hier auf, sondern rufen wir die Funktion, die
wir als Parameter
übergeben, nicht
direkt hier so. Und jetzt müssen
wir natürlich
sicherstellen, dass, wenn wir die Funktion hier
tatsächlich aufrufen,
Sie sehen, dass
hier auch ein Fehler vorliegt, den wir tatsächlich übergeben. Diese spezielle Funktion ist förderfähig. So. Wenn wir das jetzt ausführen, erhalten
wir genau das gleiche Ergebnis, aber jetzt haben wir
es etwas anders aufgeteilt, und jetzt verwenden wir Funktionen
höherer Ordnung, um die Werbeaktion zum Senden von E-Mails und
die Funktion zur Eignungsprüfung aufzuteilen Werbeaktion zum Senden von E-Mails und
die . Anstatt eine solche Funktion
definieren zu müssen,
können Sie jetzt auch
noch etwas anderes tun, nämlich eine
Lambda-Funktion verwenden. Lambda-Funktion in Python
ist eine anonyme Funktion. Also hier haben
wir keine anonyme Funktion, weil
diese Funktion einen Namen hat. Lambda-Funktion hat
keinen Namen und Sie geben ihn direkt
als Ausdruck an. Anstatt
diese Funktion hier zu haben, die wir namentlich verweisen, können
wir stattdessen eine
Lambda-Funktion verwenden. Das wird einen Kunden bekommen und es wird c zurückgeben, H ist mindestens 50. Und wenn wir das jetzt ausführen, erhalten wir
wieder
genau das gleiche Ergebnis. Aber jetzt verwenden wir eine
anonyme Lambda-Funktion. Und das ist nett,
denn jetzt haben wir eine sehr einfache Möglichkeit,
die Art und Weise zu ändern ,
wie
E-Mail-Werbeaktionen mit dem
Fehlercode behandelt werden, z. B. können
wir es auch auf
ein anderes Alter setzen, mit dem
Fehlercode behandelt werden, z. B. können
wir es auch auf
ein anderes Alter setzen, sagen wir also, nur über 60. Und jetzt werden wir ein anderes Ergebnis erzielen. Und wir mussten
an der
Werbefunktion „E-Mail senden“ nichts
ändern , was wirklich nett ist.
10. Nächste Funktionen 2/4: Lassen Sie uns dieses Beispiel
etwas komplizierter machen. Ich werde die
Lambda-Funktion hier wieder entfernen, und ich werde noch
einmal anrufen, ist berechtigt und ich werde Ihnen eine weitere Möglichkeit zeigen,
mehr Kontrolle darüber zu haben , was passiert,
wenn Sie eine Funktion aufrufen. Nun haben wir natürlich keine Möglichkeit,
diesen Wert zu
kontrollieren, wenn wir ihn haben, für eine Beförderung in Frage kommt wir ihn haben , weil er in der Funktion
fest codiert ist. Vielleicht möchten
wir hier also die Option haben
, ein Mindestalter festzulegen, das eine ganze Zahl sein wird. Und dann können
wir, anstatt
die 50 Jahre zu verwenden, die Acht
kreuzen, oder? Das ist also wirklich nett. Aber jetzt haben wir
hier ein Problem , das
förderfähig ist. Natürlich entspricht es nicht mehr
der Art dieser
Leichtgläubigen, die wir hier hatten. Und das liegt daran, dass es jetzt diesen zusätzlichen Parameter gibt
, den wir angeben müssen. Sie können eine
Sache tun, z. B. liefern, einen Standardwert wie diesen. Und dann ist das
eine Art Workaround, denn
jetzt funktioniert es wieder. Aber jetzt gibt es immer noch keine
Möglichkeit, das Alter
hier in irgendeiner Weise zu ändern , da wir nur den
Standardwert verwenden können, oder? Hier kann
uns das
Funk-Tools-Paket eine nette Lösung bieten , die
als partielle
Funktionsanwendung bezeichnet wird . Was bedeutet
Paketfunktionsanwendung? Das bedeutet im Grunde, dass
Sie, wenn Sie eine Funktion mit paar verschiedenen Parametern haben,
wie wir sie hier haben , mit partiell
bereits einige
dieser Argumente anwenden können . Und dann bekommst du
eine weitere Funktion zurück. Wenn
Sie diese Funktion aufrufen, werden
die Argumente verwendet, die Sie
zuvor angewendet haben. Sie können also die
Signatur des Headers
der Funktion ändern , indem Sie
bereits einige Werte angeben. Also zum Beispiel was wir hier tun können, lassen Sie uns
zuerst aus Tools importieren, was das Modell ist, das
wir verwenden werden. Und dann können Sie diesen
Standardwert hier wieder entfernen, damit wir den Fehler beheben. Sie können jetzt sagen,
nun, das haben wir, ist berechtigt. Und nehmen wir an, wir
wollen bei 60 kürzen, also nennen wir
es „berechtigt 60“, was eine teilweise Bewerbung von ist beförderungsfähig. Aber wir werden
es mit einem Mindestalter von 60 Jahren anbieten. Und jetzt, wo wir
E-Mail-Werbung gesendet haben, können wir sie versenden, wir können sie mit der teilnahmeberechtigten Funktion 60 teilweise
angewendet versehen. Partiell erhält also eine Funktion. Es wendet einen Wert auf eines seiner Argumente an und
gibt eine neue Funktion zurück, die jetzt aufgerufen wird,
ist wählbar 60. Leider werden hier nicht genau beschrieben, um welchen Typ
es sich bei dieser teilweise
angewandten Funktion handelt. Vielleicht kommt das in einer zukünftigen Version
von Python,
aber das ist wieder eine Funktion und die wird jetzt durch gesendete E-Mail-Werbung
aufgerufen. Wenn ich das mache, bekommst
du Kunden,
die älter als 60
sind. Dies ist also ein Beispiel partielle
Funktionsanwendung, die
wirklich leistungsfähig ist und es
Ihnen ermöglicht, Funktionen zu modifizieren , zu
vereinfachen und zu verwenden, sie
mit anderen Bereichen
Ihrer Anwendung kompatibel zu
machen, sie
mit anderen Bereichen
Ihrer Anwendung kompatibel zu
machen indem Sie bereits einige der Werte
anwenden.
11. Next-Level Funktionen 3/4: Eine weitere nette Sache, die Sie mit Func-Tools machen
können sind sogenannte zwischengespeicherte Eigenschaften. Sie erinnern sich vielleicht an das Beispiel, das
ich Ihnen in einer
der vorherigen Lektionen gezeigt habe, in dem ich eine Person hatte und wir hatten eine
Suchzeicheneigenschaft, und das war eine
berechnete Eigenschaft. Jedes Mal, wenn Sie die Eigenschaft
aufrufen, ist
der Wert Computer. Das ist vielleicht nicht immer das, was man will,
wenn der Wert
eine Drei berechnet, also mit
der
Suchzeichenfolge, so schlimm war es nicht. Aber wenn es wirklich komplex ist, sollten
Sie vermeiden, dass Sie das jedes Mal
berechnen müssen , wenn
Sie die Immobilie aufrufen. Eine Möglichkeit, dies zu lösen,
besteht darin,
den Wert tatsächlich in dem Objekt zu speichern , das Sie bei der
Erstellung des Objekts
berechnet haben . Wenn Sie jedoch
eine eingefrorene Datenklasse verwenden , ist
das nicht möglich. Hier kommen zwischengespeicherte Eigenschaften von Funktionen
ins Spiel. Also hier habe ich ein Beispiel
dafür, wie es verwendet wird. Ich habe einen Klassendatensatz, der
eine Zahlenfolge enthält. Und in diesem Fall speichere
ich
das einfach als Tupel in einer Dateninstanzvariablen. Und dann habe ich Barvermögen, das ist die Standardabweichung
dieser bestimmten Daten. Und ich verwende die
Standardabweichungsfunktion aus der Statistik. Und dann nach der
Hauptfunktion, wo im Grunde eine Instanz
dieses Datensatzes
erstellt wird. Und dann drucke ich
die Standardabweichung aus. Und was wirklich interessant ist , wenn ich das jetzt starte, sehen Sie
, dass wir diese Nachricht nur
einmal ausdrucken, um die Standardabweichung zu berechnen. Und das liegt daran,
dass das zwischengespeichert wird. Die Eigenschaft wird
einmal berechnet und jedes Mal, wenn Sie sie danach
aufrufen, einfach
anhand des zwischengespeicherten Werts. Es ist also wirklich mächtig, wenn ich dafür eine normale
Eigenschaft verwenden würde. So. Und jetzt führe
ich das noch einmal aus, Sie sehen, dass die
Standardabweichung dreimal berechnet
wird. Das ist der Unterschied.
Also werde ich dieses echte Barvermögen in Besitz nehmen. Und wenn wir das jetzt erneut ausführen, wird es wieder nur einmal berechnet. Sie verwenden also eine
Bargeldeigenschaft, um sich einen
bestimmten Wert zu merken , sodass
Sie ihn nicht immer wieder
berechnen müssen, aber Sie haben immer noch die
Flexibilität, wie auf eine normale
Immobilie in Ihrem Objekt
darauf zuzugreifen .
12. Nächste Funktionen 4/4: letzte coole Sache, die ich dir von
Fontanelles zeigen
möchte , ist Single Dispatch. Single Dispatch ist ein
Dekorator, den Sie verwenden können , um eine Art
Funktionsüberladung vorzunehmen. Sie definieren also eine generische Funktion
und registrieren Varianten dieser Funktion
, die verschiedene Typen verarbeiten können. Hier ist ein Beispiel. Ich habe eine einzelne Dispatch-Funktion namens add, die ein x und ein y,
zwei ganze Zahlen, hat und
die Summe zweier Ganzzahlen zurückgibt. Aber dann füge ich eine zweite
Version dieser Funktion hinzu. Das ist also, sagen wir,
die Standardversion der Funktion
, die ganze Zahlen erhält. Zweiter, der
Fäden und Schnüre bekommt. Ich möchte sie nicht
direkt so hinzufügen. Ich möchte ein Leerzeichen hinzufügen. Also verwende ich hier die
Zeichenkettenformatierung, um
ein Leerzeichen zwischen dem X und
dem Y einzufügen die
Zeichenkettenformatierung, um
ein Leerzeichen zwischen dem X und . Ich komme in einer Minute darauf zurück
, aber
dann aber
dann siehst du, dass die
erste Zeile, die gedruckt
wird, tatsächlich die Summe und die mit dem
Leerzeichen dazwischen
verknüpften Zeichenketten ist. Und es gibt noch mehr Dinge, die du
damit machen kannst . Sie können z. B. auch den Unionstyp verwenden, über
den
ich im Tippvideo gesprochen habe. Also registriere ich hier eine Version
dieser Funktion, die ein X und ein Y
benötigt, das ist entweder eine Liste oder eine Menge. Und das gibt eine Liste zurück, indem einfach die Elemente
in der Liste der Sätze verkettet werden. Und es gibt auch eine
funktionale Form. Diese verwenden also einen sogenannten Decorator mit
dem Add-Zeichen davor. Sie können das Punktregister aber auch einfach als Funktion
aufrufen und dann den Typ und dann die Funktion angeben, die damit umgehen
soll. Das ist es also, was Sie hier tun
sehen. Also kann ich das einfach noch einmal wiederholen
und die Liste der OECD zur Rückgabe. Und der letzte gibt ein Tupel zurück ,
weil wir das hier
angegeben haben. Gib ein schnelleres Tupel
aus, dann gibst du auch ein Tupel zurück. Sie können also Single
Dispatch verwenden, um
Objekte verschiedener
Typen in Python reibungslos zu handhaben . ehrlich zu sein, habe ich das nicht so oft
benutzt, aber ich denke, es ist nützlich
zu wissen, dass es sie gibt. Und in einigen Fällen kann
es tatsächlich hilfreich sein, Ihren Code ein wenig
zu vereinfachen. Insgesamt denke ich, dass
die Funk-Tools-Bibliothek eine wirklich interessante
Sammlung von Tools ist. Da sind noch ein paar andere
Dinge drin, die heute in dieser
Lektion
nicht behandelt wurden. Sie können sich die Dokumentation
ansehen. Aber insgesamt finde ich
es wirklich interessant. Wie mir auch aufgefallen ist
, neigen viele Leute dazu, sich an Klassen
zu halten, wohingegen Funktionen
tatsächlich auch sehr mächtig sind. Daher
ermöglichen sie Ihnen oft auch,
Ihren Code zu vereinfachen , anstatt überall Klassen zu
verwenden. Also das nächste Mal schreibst du ein Python-Programm und hast es mit komplexen
Klassen und allem zu tun. Überlegen Sie, wie
Sie
daraus eine funktionalere Version machen können. Und Sie werden oft feststellen
, dass der Code kürzer und einfacher zu lesen
sein wird . Das sind also unterhaltsame Tools und eine Art funktionale
Programmierung in Python. nächsten Lektion
werde ich mir ein
weiteres Konzept ansehen, das Sie wirklich hilfreich finden
möchten, nämlich die gleichzeitige Programmierung.
13. Gleichzeitige Programmierung 1/3: Vor allem, wenn Sie anfangen, Python professioneller zu verwenden, werden
Sie plötzlich mit einer API, einer Datenbank oder allem,
was
im Grunde über ein Netzwerk erfolgt,
interagieren . Und wenn Sie das tun, bedeutet das,
dass es
für Ihre Anwendung wichtig wird, diese Arten von
Anfragen effizient zu bearbeiten. Denn wenn Sie dies nicht tun,
wird
Ihre Bewerbung sehr langsam sein. In Python können Sie
das asynchrone IO-Paket verwenden ,
um Ihnen dabei zu helfen. Und das beruht auf etwas, das als
Parallelprogrammierung bezeichnet wird. Möglicherweise haben Sie den Begriff Parallelität bei
gleichzeitiger Programmierung und den verwandten
Begriff Parallelität,
parallele Programmierung,
schon einmal gehört gleichzeitiger Programmierung und den verwandten
Begriff Parallelität,
parallele Programmierung,
schon einmal . Diese Dinge sind eigentlich
nicht dasselbe. Es gibt verschiedene.
Der Unterschied besteht darin, dass Sie
durch paralleles
Rechnen tatsächlich über separate
parallele Verarbeitungseinheiten verfügen , um separate Aufgaben auszuführen. Wenn Sie also eine
Anwendung haben, die
mehrere Dinge
gleichzeitig erledigt, werden
diese Dinge
tatsächlich parallel zur gleichen Zeit ausgeführt. Parallelität
und Parallelität bedeuten also, dass eine Anwendung bei mehreren
Aufgaben gleichzeitig Fortschritte
macht. Aber anstatt
echte Paralleloperationen zu haben, wird
es tatsächlich dynamisch
zwischen diesen Aufgaben wechseln . Nehmen wir also an, eine Anwendung
als Aufgabe A zu Aufgabe B, sie fängt einfach an, ununterbrochen mit A zu
arbeiten, fährt mit B fort, ein bisschen B, und geht dann zurück zu A und
so weiter und so fort. Es ist also nicht parallel, sondern es wird einfach
zwischen den beiden gewechselt. Weil das sehr schnell geht. Als Benutzer haben Sie vielleicht die Vorstellung, dass es parallel
passiert, aber tatsächlich
passiert es gleichzeitig. Es wechselt einfach. Es ist wie der Unterschied zwischen parallelen
Warteschlangen vor einer
Kassiererin. Das bedeutet, dass wir
mehrere Kassierer haben und jeder Kassierer eine Leitung hat
, die er bearbeitet. Parallelität bedeutet, dass
es einen Kassierer gibt, aber es gibt mehrere Warteschlangen und jeder wechselt sich ab. Die Zeilen
sind in diesem Fall die Aufgaben, die ein Computer lösen muss, und
die Kassierer sind die CPUs. Moderne Computer
verwenden eine Kombination
aus Parallelität und Parallelität. Wissen Sie, Ihre CPU hat vielleicht 246810 Kerne, die alle Dinge parallel
erledigen können, aber Ihr Betriebssystem wird
Dutzende bis Hunderte
verschiedener Aufgaben haben . Und es wird eine Teilmenge
dieser Aufgaben parallel auf
diesen verschiedenen CPU-Kernen
ausführen , aber dann wird es auch gleichzeitig zwischen
ihnen
wechseln. Parallelität in Python
hat eine Einschränkung
, da Python über diese sogenannte
globale Interpretersperre verfügt. Und das heißt, wenn
Sie, sagen wir,
mehrere Threads haben , die parallel sein
sollen, die
in Python eigentlich parallel sein könnten, funktioniert
das nicht,
weil sie an den Interpreter
gebunden sind . Dafür gibt es Gründe. Darauf werde ich
in dieser Lektion nicht eingehen. Aber die Konsequenzen
, die durch Parallelität in Python nicht
wirklich möglich sind. Es gibt ein paar
Workarounds, z. B. könnten
Sie, anstatt einen einzigen Prozess
zu haben, das
Multiprocessing-Backedge verwenden , um
mehrere Prozesse zu erstellen. Und Dan, du
hast Parallelität. Sie können auch zu
einem anderen
Python-Interpreter wechseln , diese globale
Interpretersperre
nicht hat. Aber eigentlich gibt es
nicht viele Fälle, in denen
Sie Parallelität benötigen. Oft ist Parallelität
schon richtig gut und Python bietet eine sehr gute
Unterstützung für Parallelität, insbesondere seit Python 3.7, das das
Async-IO-Paket stark verbessert hat. Jetzt ist Parallelität wirklich
wichtig, da Sie
dadurch
mehrere Aufgaben haben können, z. B. eine Aufgabe zum Abrufen
einiger Daten von einer API. Während Sie auf
die Antwort der API warten, können
Sie bereits
zu einer anderen Aufgabe wechseln, und das ist auch nützlich, z. B. wenn Sie eine GUI-Anwendung haben und die GUI darauf wartet, dass Sie Text in die
Textfelder eingeben oder eine Taste drücken. Nun, da es sich um ein
Parallelprogramm handelt, können
Sie andere Aufgaben
gleichzeitig erledigen, z. B. einen
Teil des Speichers aufräumen, Daten vorab abrufen
oder was auch immer Sie tun
möchten, um
die Anwendung reibungsloser
laufen zu lassen . Und angesichts der Tatsache, dass fast
jede Anwendung heutzutage über das Internet
kommuniziert und eine Menge Daten abruft. Es ist wirklich wichtig, dass wir mit Parallelität richtig
umgehen. Und genau das ermöglicht Ihnen das
Async IO-Paket in Python.
14. Gleichzeitige Programmierung 2/3: Es gibt zwei wichtige
Schlüsselwörter, die Sie kennen sollten, wenn Sie gleichzeitigen oder
asynchronen Code
schreiben, und das sind async await. Sie können async vor
eine Funktion oder
Methode schreiben , um anzugeben , dass dies eine Funktion
oder Methode sein wird , die Sie gleichzeitig
aufrufen können. Und Sie können eine Gewichtung verwenden, um vor
einer Aussage
anzugeben, dass die nächste
Anweisung warten soll, bis die vorherige
Aussage abgeschlossen ist. Und das ist der
zweite Teil, der auch
sehr hilfreich ist , weil man oft warten
muss eine bestimmte Antwort warten
muss,
um etwas zu tun. Wenn Sie beispielsweise
Daten von einer API abrufen, müssen
Sie warten, bis
Sie zwei Daten zurück haben, damit Sie mit diesen Daten tatsächlich
etwas anfangen können. Also async und wait haben hier ein
sehr einfaches Beispiel. Sie können sehen, dass wir eine Funktion zum Abrufen von
Pokemon
haben , die die
Pokemon-API verwendet, um Pokemon-Namen zu erhalten. Und wir übergeben, in
diesem Fall eine ID und wir haben eine URL, unter der
wir die ID angeben. So
sollten wir diese API nennen. Und dann kehre ich zurück und
warte auf HTTP GET. Und dann
ist die URL http get eine Hilfsfunktion
, die ich erstellt habe. Das ist asynchron. Ich zeige dir in einer Minute, wie das
funktioniert. Aber hier sehen wir die
asynchrone Funktion Get Pokemon, die die Gewichte
zurückgibt und dann
die Daten von der URL abruft. Und wir benutzen einen Kellner
, weil wir natürlich
erst zurückkehren können , wenn
wir diese Daten haben. Die Hauptfunktion hier ist, wie Sie hier sehen können, ebenfalls asynchron, da
sie die
Funktion rent int verwendet, um
eine zufällige Ganzzahl zwischen einer
und der höchsten Pokémon-ID zu erstellen , die derzeit 898 ist. Und dann verwende ich ein Gewicht, um das Pokemon von
dieser bestimmten ID zu erhalten, und dann drucke ich den
Namen des Pokémon aus. Und hier ist das Gewicht auch wirklich
wichtig, weil ich
natürlich warten muss bis ich den Pokémon-Wert habe,
damit ich den Namen drucken kann. Das siehst du hier. Ich habe das umgangen. Siehst du, wir bekommen zufällige Pokémon
und du hast gesehen, dass es ungefähr eine halbe
Sekunde oder Sekunde
gedauert hat, bis dieser bestimmte
Pokémon-Wert erreicht ist. Versuchen wir das noch einmal. Sie sehen, es dauert eine Weile und
dann bekommen wir das Ergebnis. Das ist falsch, weil
wir warten müssen, bis die API uns antwortet,
und das kann eine Weile dauern. Hier haben wir ein weiteres
Beispiel, das Ihnen zeigt, wie wertvoll der Einsatz von
Concurrent Programming ist. Also, was ich hier gemacht habe, ist, dass ich
zwei Versionen davon habe. Holen Sie sich eine Anfrage von der API. Ich habe eine asynchrone Version und ich habe eine
synchrone Version. Hier haben Sie eine Funktion, die die synchrone Version
verwendet. Was ich also mache, ist,
dass ich Pokemon von dieser bestimmten URL erhalte. Und hier habe ich keine
asynchrone Version , die dieses Pokemon bekommt. Und in diesem Fall verwende ich die asynchrone
HTTP-GET-Funktion. In meiner Hauptfunktion habe ich dann
nach synchronen Aufrufen zwei Versionen. Das wirkt sich also im Grunde jedes Mal auf die Ergebnisse aus, oder? Also mache ich einen For-Loop und
erhalte 20 zufällige lokale Namen und berechne dann
die Gesamtzeit. Und im asynchronen Aufruf verwende
ich etwas namens
Async IO Dot Gather. Und das
ermöglicht es mir, es mit
einer Anzahl von Anrufen und einer Anzahl
von asynchronen Anrufen zu versorgen , dann wird es sie starten,
immer will Ameisen, anstatt zu warten, dass jeder Monat endet, bevor
der nächste beginnt Async Aorta Gather ermöglicht es uns all diese Dinge
gleichzeitig
auszuführen. Wenn Sie das also ausführen, sehen
Sie das, obwohl dies das erste Mal
ist. Jetzt hast du gesehen, dass wir
im synchronen Fall fast 2 Sekunden gebraucht haben, um diese 20 Pokémon-Namen zu
bekommen,
weil wir auf den ersten
warten bevor wir
den zweiten anfordern. Und im asynchronen Fall dauerte
es nur 0,9 s, das ist
also weniger als die Hälfte. Und das liegt daran, dass wir die Dinge gleichzeitig
ausführen. Wir müssen nicht auf
die Ergebnisse des
ersten API-Aufrufs warten . Um den zweiten API-Aufruf
zu starten, müssen Sie vorsichtig sein,
nämlich dass diese
APIs häufig Raid-Limits haben. Sie möchten also nicht etwa 1.000
API-Aufrufe oder -Wünsche
starten , weil
sie nicht akzeptiert werden. Sie müssen
die API-Anfrage also innerhalb
bestimmter Ratenlimits ausführen , z. B. eine feste Anzahl von Aufrufen, z. B. eine maximale Anzahl
von Aufrufen pro Sekunde,
hängt davon ab, ob die API das nachschlagen
sollte. Aber wie Sie sehen
können, wenn Sie ein wenig
darüber nachdenken , wie wir unseren
Code asynchron ausführen können, wie er gleichzeitig ausgeführt werden kann. Das erspart uns
viel Wartezeit und unsere Anwendung
läuft dadurch viel reibungsloser. Also das ist gesammelt, gesammelt
Im Grunde das, was Sie hier sehen, entpacke
ich eine Liste
verschiedener asynchroner
Funktionsaufrufe. Das ist also async io.gov
, ein wirklich nützliches Tool
, um Dinge gleichzeitig auszuführen. Und alles, was hier in
diesen Beispielen zu sehen ist, ist, dass wir
diese asynchrone Hauptfunktion haben , aber wir führen sie mit
asynchronem IO-Punktrum aus
, der den
Python-Interpreter anweist,
diese Hauptfunktion
asynchron auszuführen . Und lass uns brauchen, denn
wenn ich einfach main schreibe, dann wird das eigentlich nicht
wie beabsichtigt funktionieren. Denn wenn ich diese Klimaanlage betreibe, bekommen
wir alle
möglichen Warnungen, dass die Routine in Maine
niemals warten würde. Und genau das
passiert natürlich hier. Wir nennen es einfach. Also, wenn du das
vermeiden willst,
dann solltest du
async IO dot run aufrufen async IO dot run und das
natürlich korrekt schreiben, Doctrine. Und dann nennen wir die
Hauptfunktion so. Wenn ich das
erneut ausführe, sehen Sie, dass wir den
Fehler
jetzt nicht mehr haben.
15. Gleichzeitige Programmierung 3/3: Als letztes
möchte ich Ihnen zeigen, wie synchronen Code, nicht gleichzeitigen Code, in Code umwandeln
, der gleichzeitig ausgeführt wird. Und das kann
manchmal passieren, wenn Sie
ein Bibliothekspaket haben , das Sie verwenden und es ist nicht asynchron, aber Sie möchten es
in einen asynchronen Aufruf umwandeln. Wie machst du das? Also ich habe hier ein Beispiel. Es gibt hier also eine asynchrone
Funktion, einen Zähler, und hier gibt es auch eine Funktion für
synchrone
Sendeanfragen . Und das bedeutet einfach, das Paket Anfragen
schreiben zu
verwenden , nicht das Anforderungspaket eigentlich nicht asynchron
und synchron ist. Das heißt, wenn wir hier eine Anfrage
senden, müssen
wir auf das Ergebnis warten und geben einfach
den Statuscode zurück. In diesem Fall habe ich
meine Hauptfunktion hier und schicke eine Anfrage
an unsere Alkohole sind weg, das ist meine Website. Und dann drucke ich
die HTTP-Antwort mit diesem Status und rufe dann
den Zähler auf. Eine andere Sache ist natürlich, warum sollten wir hier auf
die Antwort warten ,
um den Zähler zu starten? Das ist alles. Brauche es, oder? Wenn ich das ausführe, siehst du,
dass wir die Anfrage senden, dann haben wir die Antwort und dann fangen wir an zu kontern. Was wäre, wenn wir
Gathered verwenden möchten, um gleichzeitig
mit dem Senden der Anfrage
einen Zähler zu starten . Wie machen wir das? Nun,
wenn wir das tun wollen, heißt
das, dass wir Anfrage
senden und so weiter schalten müssen. Asynchrone
Parallelfunktion statt einer synchronen Funktion, wenn Sie dies tun möchten,
ist das eigentlich ganz einfach. Anstatt also solche
Sendeanfragen aufzurufen
, können Sie dann zwei Threads
asynchronisieren. Wird
daraus ein Thread? Und dann
rufen wir an, senden Sie eine Anfrage. Wir müssen auch die
Argumente angeben, das ist die URL. Und dann müssen wir ein
Gewicht davor schreiben, weil
die Bedrohung diese Funktion
in eine asynchrone Funktion verwandelt . Also lassen Sie mich das ausführen und Sie sehen, wir bekommen immer noch
genau das gleiche Ergebnis, oder? Weil wir kein Gewicht haben. Also senden wir die Anfrage, erhalten die Antwort und starten dann
den Zähler. Aber jetzt, wo wir die
asynchrone Version hier haben, können
wir
Asynchrony All Dot
Gather verwenden , um diese beiden
Dinge gleichzeitig zu erledigen. Also hier haben wir ein Beispiel
, in dem ich das eingerichtet habe. Also, was ich getan habe,
ist, dass ich jetzt
eine weitere Funktion namens
sent async request erstellt habe eine weitere Funktion namens
sent async request , die
einen asynchronen IO-Punkt verwendet, um zu
drohen, diese asynchron aufzurufen. Und dann
habe ich in meiner Hauptfunktion keinen asynchronen IO-Dot-Gathering. Und dann habe ich
die asynchrone Anfrage gesendet oder die eine Funktionsstörung verursacht, wodurch die Drohung verwendet dies in eine
asynchrone Funktion
umzuwandeln. Und ich benutze auch Zähler. Und wenn ich das durchführe, wirst
du dafür sorgen, dass wir den Zähler
bekommen. Und es beginnt
gleichzeitig mit dem Senden einer Anfrage. Und dann warten wir und am
Ende bekommen wir die Antwort. Das ist also asynchrones IO. Übrigens, hier hatten wir unsere asynchronen Get Pokemon Leute
, die dieses HTTP GET verwendeten, eine
Hilfsfunktion, die ich erstellt habe. Das steht tatsächlich in dieser Akte. Und Sie sehen, dass wir hier
Async IO dot two
thread verwenden , um
die
Funktion Request dot gets in einen
asynchronen Funktionsaufruf umzuwandeln die
Funktion Request dot gets . Das verwendet also genau
den gleichen Mechanismus, um zu
schließen, dass asynchrones IO eine sehr
leistungsstarke Funktion von Python ist. Gleichzeitiges Programmieren ist im
Allgemeinen sehr nützlich, insbesondere wenn Sie über ein Netzwerk mit
anderen Diensten
kommunizieren und möchten Ihre Anwendung reibungslos
verhält. Ich hoffe, diese Lektion hat Ihnen
einige Ideen gegeben , wie Sie
Ihren eigenen Code
in asynchronen Code umwandeln können , insbesondere wenn Sie einen Großteil
dieser API- oder
Datenbankkommunikation
durchführen . In den verbleibenden
Lektionen dieses Kurses werde ich manchmal auf
die gleichzeitige Programmierung zurückkommen. Zeigt Ihnen, wie Sie
diese Funktion insbesondere unter Berücksichtigung der
gleichzeitigen
Programmierung verwenden können . der nächsten Lektion
geht es nun um Iteratoren.
16. Iteratoren 1/3: In dieser Lektion werde
ich
über Iteratoren in Python sprechen . Was kein Iterator ist,
obwohl es sich im Grunde ein Objekt handelt, an dem iteriert
werden kann, können
Sie alle Werte
durchgehen. Sie können einen
Iterator in Python erkennen weil er
das Iteratorprotokoll implementiert, was bedeutet, dass er
die nächsten Domino-Methoden hat. Iteratoren gibt es
überall in Python, sie werden für Schleifen verwendet, sie verwenden Listenverständnisse und an vielen anderen Stellen, an denen
Sie
sie wahrscheinlich schon
einige Male verwendet haben, ohne zu wissen, dass es sich um Iteratoren handelt. Möglicherweise haben Sie
die Begriffe Iterator
und Iterable gehört . Sie sind nicht dasselbe. Ein iterierbares Objekt, das Ihnen
einen Iterator zur Verfügung stellen kann. Und das bedeutet, dass es
die Methode itr dunder hat , denn das gibt Ihnen einen Iterator. Ein Iterator neben der
itr-Donor-Methode hat auch eine nächstdominante Methode
, mit der wir das nächste Element
in der Iteration
abrufen können . Einige dieser Iteratoren
sind endlich, z. B. können
Sie durch
eine feste Liste von Elementen iterieren. Einige dieser Iteratoren
sind unendlich. ZB können Sie über
alle Integer-Werte iterieren. Natürlich gibt es in Python keinen Maximalwert für eine Ganzzahl, zumindest ein paar Mal, dass Ihr Arbeitsspeicher
auf Ihrem Computer begrenzt ist. Also Listen, Tupel,
Wörterbücher, Mengen, Zeichenketten, das sind Dinge,
die alle iterierbar sind. Und Sie können einen Iterator
von ihnen bekommen und dann
können Sie durch die
bestimmte Sequenz iterieren. Schauen wir uns ein paar Beispiele
an. Ich habe hier eine Hauptfunktion, und es gibt einen Klassengegenstand, einen Namen und ein Gewicht
hat,
für jeden Gegenstand hat ein Gewicht. Ich verwende offensichtlich
Datenklassen. Und dann nach der
Hauptfunktion, wo auch immer, eine Liste der Artikel und ich nenne
das ein Inventar. Was ich jetzt tun kann, ist eine Liste zu
inventarisieren, das ist
also iterierbar. Also kann ich daraus einen
Iterator machen. Damit ich Inventar schreiben kann. Der Iterator entspricht dem
Inventarpunkt Dr. Hitter. Das gibt mir den Iterator und dann kann
ich zB den
Inventar-Iterator-Punkt
und dann Dahmer als nächstes drucken . Das verwendet also das
Iterator-Protokoll. Wenn ich das ausführe,
sehen Sie, dass es
das erste Element in
dieser iterativen Sequenz druckt . Wenn ich diese Zeile so kopiere, ruft sie Max
zweimal an und es wird das zweite Element
durchgehen. Das siehst du hier. Es gibt einen etwas
einfacheren Weg dies
zu tun, anstatt
diese Dunder-Methoden aufzurufen.
Was wir auch
tun können, ist genau richtig. Sie ist es, eine Hilfsfunktion, die für uns einfach die dominante
Methode
aufruft. Und in ähnlicher Weise
können wir auch next verwenden, was für uns die nächste dominante
Methode aufruft. So. Und jetzt bekommen wir genau
das gleiche Ergebnis. Also kann ich das einfach
weitermachen. Also, hier sind sechs Artikel drin. Also werde ich jetzt alle
Artikel in dieser
speziellen Liste ausdrucken . Was passiert also, wenn
ich noch einen hinzufüge? Nun, dann wird das einen Stopp-Iterationsfehler auslösen. Sie sehen also, dass wir hier einen Traceback
erhalten, es gibt eine Stopp-Iteration. So zeigt ein
Iterator also an: Hey, es gibt keine mehr, ich kann dir
etwas anderes geben . Also könntest du
jetzt zB eine While-Schleife
erstellen
und dann eine try
except-Anweisung einfügen und dann fangen, die
Wiederholungen davon stoppen, dann, du weißt schon, bist du dämlich. Aber natürlich
verwendet niemand Iteratoren auf diese Weise. Es ist nicht viel
einfacher, das zu tun, und zwar indem man einfach eine For-Schleife
verwendet. Lassen Sie mich also einfach
all diese Dinge hier entfernen. Und dann schreibe ich
für Artikel im Inventar. Und dann werde ich
den Artikel einfach
mit einem Semikolon drucken , wirklich. Da gehen wir rein und
drucken einfach alle Artikel aus. Was die For-Schleife also
unter der Haube macht, ist, dass sie die Methode iter und next
verwendet, also zuerst einen
Iterator erhält und dann nächste wiederholt so oft aufruft , bis sie auf
den Stopp-Iterationsfehler stößt und dann stoppt sie. Das macht die For-Schleife
. Sonst nichts. Das Schöne an der
Iter-Funktion, die
die Donor-Methode aufruft , ist, dass Sie
ihr auch einen Sentinel-Wert geben können . Und es ist im Grunde ein Wert
, der
angegeben werden sollte, um das Ende
des Iterators anzuzeigen. Dies ist z. B. nützlich,
wenn Sie
Daten aus einer Datei oder einem Netzwerk lesen , im Grunde genommen aus einem
Datenstrom, und Sie möchten wissen, dass das Ende des
Streams erreicht wurde. Also ich habe hier ein Beispiel. Das ist also eine Datei namens Country's, die ein
paar Länder enthält. Und dann kann ich
den Sentinel-Wert verwenden , um anzugeben, was das
Ende der Datei ist. Ich kann also Breitenanweisungen verwenden. Das ist ein Kontext-Manager. Darüber werde ich
in einer späteren Lektion sprechen. Und ich werde Open verwenden
und dann werde ich die TXT-Datei mit
den Länderpunkten öffnen . Und dann mache ich für die
Schlange in einem amüsanten Enter. Und dann
ruft es phi dot read line auf, was etwas Iterable zurückgibt. Und der Sentinel-Wert
wird die leere Zeichenfolge sein. Und dann werde
ich die Zeile drucken. Also, wenn wir das tun, dann sehen Sie, dass wir
all diese Länder bekommen. Und weil die Textdatei
bereits neue Zeilen enthält, kann
ich sie einfach
aus der Print-Anweisung entfernen, indem angebe, dass das Ende
der Print-Anweisung die leere Zeichenfolge
ist. Und dann wird
es ein bisschen schöner aussehen. Die leere Zeichenfolge
hier wird also
als Sentinel-Wert verwendet , um anzuzeigen , dass wir
das Ende der Datei erreicht haben.
17. Iteratoren 2/3: Da wir diese
Iterables und Iteratoren haben, ermöglichen
sie uns auch, eine gewisse Abstraktion
einzuführen. Also hier habe ich ein anderes Beispiel. Also hier ist eine Einzelartikelklasse. Es ist eine eingefrorene Datenklasse. Darüber habe ich zu
Beginn des Kurses gesprochen. Und jeder Einzelartikel hat
einen Preis und eine Menge. Das ist der Gesamtpreis, das gibt eine Ganzzahl zurück, und das ist einfach der Preis
multipliziert mit der Menge. Und dann gibt f for function
Summen aus, die Elemente erhalten. Und ich sehe, dass ich ihm
keine Liste von Einzelpunkten übergebe, sondern eine iterative Liste von
Einzelpunkten und Prinzipien. Das einzige, was ich tun würde
, ist,
die For-Loop für Artikel
in Artikeln zu verwenden und einen Prinzen, den Gesamtpreis in
meiner Hauptfunktion, ich habe eine Liste von Einzelartikeln. Schau dir das hier an, und dann nenne
ich Gesamtwerte drucken. Wenn ich das ausführe,
werden einfach alle Summen
ausgedruckt. Aber das Schöne ist
jetzt, dass
print totals
etwas erwartet, das iterierbar ist, es eigentlich
egal ist, ob das eine Liste oder ein Tupel
oder etwas anderes ist. Also zB hier, wenn meine
Einzelposten auflisten, kann
ich das
durch ein Tupel ersetzen, so. Jetzt ist es also keine Liste mehr, aber die Gesamtwerte drucken ist mir egal. Solange es iterierbar ist, kann
es seinen Job machen. Iteratoren können
Sie also auch eine
gewisse Abstraktion einführen , da sich Prints Altos nicht um
die Datenstruktur kümmert. Es kümmert sich nur darum, dass es etwas
hat, über das es iterieren kann
, und das ist alles, was es braucht.
18. Iteratoren 3/3: Wenn Sie
Iteratoren wirklich auf die nächste Stufe bringen möchten,
können Sie auch GitHub-Tools verwenden. Dabei
handelt es sich um ein Paket
, ein
Standardpaket
von Python, das über
sehr leistungsstarke
Iteratormechanismen verfügt . Es ist eine Art
Algebra von Iteraten. Wie Sie alle diese
Iteratoren nehmen können, kombinieren Sie sie auf
unterschiedliche Weise , um ein
wirklich komplexes Verhalten zu erzielen. Nehmen wir zum Beispiel an, Sie möchten zuerst Elemente
aus einer Liste
herausfiltern und diese Elemente dann mit einem anderen Wert
aus einer anderen Liste
multiplizieren und sie dann
mit einem anderen Satz von Werten verknüpfen, indem Sie dafür normalerweise eine Kombination
von Funktionen
und For-Schleifen verwenden würden . Sie können aber auch
andere Tools verwenden , um
diese Operationen
mithilfe der Iteratoralgebra
zu einer großen Operation zu kombinieren . Ich zeige Ihnen ein paar
Beispiele, wie das funktioniert. Um es also nicht zu benutzen, die
Tools, müssen
wir es natürlich importieren. Das wird gehen. Und dann gibt es ein paar Dinge,
die du tun kannst. Es klingt sehr einfach,
aber es gibt ein paar wirklich fortgeschrittene Dinge, die Sie mit Iteratoren machen
können. Also werde ich noch einmal mit
meiner Inventarliste beginnen , weil das
nützlich sein wird, um Ihnen zu zeigen,
was Sie mit Iteratoren machen können. Ich werde
diese Zeilen hier einfach entfernen. Nun, fangen wir mit
etwas ganz Einfachem an. Ein wirklich einfaches
Beispiel ist count
, eine Funktion
von itertools, Sie
ab einer bestimmten Zahl hochzählen
können. Wir können also einen For-Loop verwenden,
weil er iterierbar ist, oder? Wir haben Zählungen und dann können wir z.B. den
Startpunkt
angeben. Also wollen wir um zehn anfangen zu
zählen. Und Sie können sogar einen Schritt
angeben, z. B. mit Fünferschritten und I ausdrucken. Wenn ich
jetzt hier aufgehört habe,
geht das im Grunde unendlich
weiter. Also, wenn Chi gleich ist, sagen
wir 50, dann werden
wir kaputt gehen. Also, wenn ich das mache, dann ist das, was du bekommst. Das ist also die
Zählfunktion, counts Iterable. Kein einfaches Beispiel ist eine Wiederholung. Das wird sich jetzt
also 105 Mal wiederholen. Lassen Sie uns das ausführen und dann sehen
Sie dass
genau das passiert. Sie
können auch akkumulieren, wodurch die Teilsummen berechnet werden. Nehmen wir an, wir haben Zwischensummen, was, sagen wir, eine
Liste einiger Zahlen ist. Ich tippe hier nur zufällige
Dinge, so. Und dann können
wir das Akkumulieren verwenden. Und wir werden
ihm die Liste der Zwischensummen liefern. Aber Sie könnten es
tatsächlich bereitstellen, im Grunde jedes andere Iterable das Sie ein anderes It's Tools,
functions
verwenden könnten für das Sie ein anderes It's Tools,
functions
verwenden könnten, und dann werde
ich einfach I
drucken und das
brauchen wir in diesem Fall nicht. Was jetzt
tun wird, ist diese Liste
von Zwischensummen
durchzugehen diese Liste
von Zwischensummen
durchzugehen und jedes Mal die
Teilsumme zu berechnen, so weiter. Das bekommen wir als Ergebnis. Weitere Dinge, die Sie
damit machen können, regeln sich. Nehmen wir an, wir
haben Spielkarten, was eine Liste von, sagen
wir, Zeichenketten ist. Ich verwende GitHub
Copilot hier, um das für mich zu generieren, sodass
ich das nicht wirklich eingegeben habe. Aber jetzt können Sie
Permutationen verwenden. Funktionierende Permutationen. Es sind die Werkzeuge all
dieser Spielkarten. Und nehmen wir an, wir wollen
alle Permutationen von haben, das war's für Spielkarten. Und dann lassen Sie uns die drucken. Da Fermentationen
wieder auf seinem Ribosom sind,
kann ich eine for-Schleife verwenden, um darüber zu
iterieren. Sie werden gehen. Und wenn wir das ausführen,
nun , das ist es, was wir bekommen. Jetzt haben wir also alle
möglichen Kombinationen von vier verschiedenen Spielkarten. Und lassen Sie uns das ein
bisschen einfacher machen,
damit Sie ein bisschen besser
sehen können, was passiert. Also
erstelle ich einfach A, B und C.
Nehmen wir an , wir wollen
alle Kombinationen von zwei haben. Und dann bekommen wir
das, oder? Sie sehen also, dass die Reihenfolge hier
tatsächlich wichtig ist. Also AB ist etwas anderes als ba, wenn die Reihenfolge keine Rolle spielt, du benutzt keine Permutationen, sondern du benutzt Kombinationen, dann bekommen wir das hier. Natürlich gibt es
viel weniger Kombinationen dieser drei
Zeichen, AB, AC
und BC, statt einer
For-Schleife, um jeden Wert zu drucken, können
wir auch etwas anderes verwenden. Wir können den Listeninitialisierer verwenden,
um die Ergebnisse
dieser Kombinationen iterierbar in
eine Liste umzuwandeln dieser Kombinationen iterierbar in , die wir
dann einfach ausdrucken können und dann erhalten wir Folgendes. Es gibt noch mehr Dinge, die
Sie mit Tools machen können, z. B. könnten Sie eine Kette verwenden. Wenn wir also Werte mit, sagen
wir, einem Analysten d,
e, f ändern sagen
wir, einem Analysten d, , dann
erhalten wir eine einzelne Liste
, die eine Kette
dieser beiden separaten Listen ist . Und natürlich können Sie hier
jede Art von Iterable übergeben. Eine andere Sache, die ebenfalls
nützlich ist, ist der Filter false. Sie können also, sagen
wir, eine Liste von It's a
tool start, filter false ausdrucken . Und ich möchte alle Artikel
mit einem Gewicht von weniger als 1 kg
herausfiltern . Also werde ich hier eine
Lambda-Funktion verwenden, bei der
x Punkt wartet, um das
korrekt zu schreiben, weniger als eins ist. Und natürlich gebe ich es mein Inventar weiter. Und dann
sollte es hier zwei Spalten geben. Ich glaube nicht, mir fehlt keine Klammer. Also, wenn ich das ausführe, dann bekommen wir das. Wir sehen also, dass wir nur den Laptop,
das Buch und die Kamera
haben , was ein Kilo oder mehr wiegt. Zum Schluss
möchte ich Ihnen eine Sternenkarte zeigen. Dies ist eine weitere Funktion
von itertools
, ist eine weitere Funktion
von itertools
, mit der
Sie eine Liste oder eine
Iterable von Tupeln erstellen können, in diesem Fall mit mehreren Werten. Und dann können
Sie für jeden Wert eine Art von Operationen anwenden. Also hier mache ich
eine Multiplikation. Also habe ich hier eine Liste von Tupeln. Das
wird also eine neue Liste
von zwei mal 68 mal
4,5 mal drei erstellen . Und das ist das Ergebnis
, das Sie hier sehen. Das ist also Sternenkarte. Und jetzt können wir uns vorstellen, dass mit diesen in zwei Funktionen Sie
mit diesen in zwei Funktionen
Dinge tatsächlich auf verschiedene Arten kombinieren können. Sie könnten also filter false verwenden, um ein neues Iterable mit
einer Teilmenge der
Elemente und der Liste zu
erstellen . Und wenn Sie Akkumulate verwenden, um das
Gesamtgewicht zu
berechnen oder so, dann können Sie die Sternenkarte verwenden,
um Wartezeiten ,
Mengen usw. zu berechnen. Sie können all diese
Kombinationen verwenden, um
eine Art Algebra zu erstellen , die
ihnen ein komplexes Verhalten erzeugt. Und das ist eine andere Art, das
zu tun, als sagen wir, For-Loops zu verwenden oder Dinge und
Funktionen
aufzuteilen und solche Dinge. Und Sie können
natürlich auch
Ihre eigenen benutzerdefinierten Iteratoren erstellen, Ihre eigenen benutzerdefinierten Iteratoren etwas
Spezifisches für
das tun, was Sie benötigen, um sie
nahtlos mit Itertools zu kombinieren ,
da dies alles
dem iterierbaren Protokoll folgt. Also hier ist eine kleine
Übung für dich. Schauen Sie sich einen Teil Ihres
früheren Codes an und sehen Sie, ob Sie einige
Beispiele finden, in denen Sie,
anstatt eine
for-Schleife zu verwenden, um die Liste zu durchqueren, die Tools
verwenden könnten anstatt eine
for-Schleife zu verwenden, um die Liste zu durchqueren, , um
diese bestimmte Operation auszuführen. Das macht wirklich Spaß und kann manchmal zu
viel kürzerem Code führen. Seien Sie jedoch vorsichtig,
denn wenn Sie
eine wirklich komplexe
Kombination von Tools verwenden , wird
dies auch
sehr schwer zu verstehen sein. Sie müssen also sicherstellen, dass
Ihr Code noch lesbar ist. Und natürlich können Sie die Dinge
immer noch gut in
verschiedene Funktionen
aufteilen , auch wenn Sie
verschiedene Werkzeugfunktionen kombinieren. In der nächsten Lektion werde
ich
faule Iteratoren, auch Generatoren
genannt, behandeln .
19. Generatoren 1/4: In dieser Lektion
werde ich über
Generatoren sprechen und es gibt spezielle
Dinge in Python, Daten erzeugen einen
sogenannten Lazy-Iterator und diese wurden eingeführt
und peppen 255. Was bedeutet eigentlich ein fauler
Iterator? Nun, es ist fast dasselbe wie ein normaler Iterator, außer dass er die Werte
nur erstellt,
wenn Sie nach dem Wert fragen. Also anstatt zu haben, sagen
wir, wenn Sie
eine Liste mit Werten haben, definieren Sie die Liste bevor Sie
sie tatsächlich wiederholen können. Sie müssen also
die gesamte Liste erstellen. Mit Lazy Iterator. Sie erstellen diese Elemente nur
, wenn Sie sie durchgehen. Das bedeutet also, dass Lazy Iterator sein
Konzept
nicht im Speicher speichert. Es erstellt den Inhalt
im Handumdrehen, wenn Sie danach fragen. Und das bedeutet, dass dies
in einigen Fällen
eine geeignetere Lösung
ist ,
als alles
vorher zu berechnen , bevor Sie mit der
Iteration beginnen . Es
generiert auch eine einfache Methode Iteratoren zu
erstellen, da
es im Grunde
eine Klasse mit den Methoden iter und next
dunder generiert , über die Sie
dann iterieren können , anstatt all
diese Dinge selbst schreiben zu
müssen. Und wie macht man
das? Nun, Sie schreiben
einfach eine Funktion, genau wie Sie
eine reguläre Funktion schreiben würden, außer dass Formen eine
Return-Anweisung verwenden, um einen Wert zurückzugeben, aber Sie verwenden yield, sowohl return als auch yield geben irgendeine Art von Wert
zurück, außer dass return die Funktion tatsächlich
beendet. Erträge. Es speichert den aktuellen Status
der Funktion und
gibt den Wert zurück. Und wenn
Sie die Funktion das nächste Mal aufrufen, wird dieser Zustand einfach
wieder abgerufen und zwar
dort, wo er aufgehört hat.
20. Generatoren 2/4: Hier habe ich ein sehr
einfaches Beispiel für eine Generatorfunktion. Sie sehen also auch, dass der Rückgabetyp ein Generator
ist und
was diese Dinge bewirken, darüber werde
ich in einer Minute sprechen. Aber das ist sehr einfach. Wir haben eine Zeichenfolge und wir geben
den Wert dieser Zeichenfolge zurück. Das ist also das erste
Mal, dass wir das nennen. Aber dann fügen wir ein
Ausrufezeichen und geben es wieder ein. Dadurch wird ein
Iterator erstellt, den Sie zweimal
aufrufen können , bevor das Rennen die Iteration beenden
muss. Und dann verwende
ich in der Hauptfunktion for-loop, um
den Iterator durchzugehen , den uns dieser einfache
Generator zur Verfügung stellt. Und dann
drucke ich die Zeichenfolge. Hier sehen Sie also, was das
Ergebnis dieser Operation ist. Sie verwenden dies also
als normalen Iterator ,
außer dass dieser Code nur
ausgeführt wird , wenn Sie die
nächste Methode das zweite Mal aufrufen. Also, was ist
dieser Typ genau? Nun, das degeneriert
den Typ, den können Sie aus der Typisierung
importieren, und das sagt uns, was
der Ertragswert ist. Sie können also sehen, dass das
tatsächlich eine Zeichenfolge ist. Und was diese bedeuten, obwohl Sie tatsächlich einen Mechanismus haben Informationen
gesendet werden, um eine Funktion zu
generieren, und diese
Informationen dann für die nächste Runde
erneut verwendet werden . Hier ist ein Beispiel aus
der Python-Dokumentation , das zeigt, wie das funktioniert. Es ist ein bisschen fortgeschritten, aber obwohl dies ein
Python-Kurs der nächsten Stufe ist, warum nicht? Aber im Grunde
genommen
speichern wir das Ergebnis
des Yield-Ausdrucks
, den wir
an diese Funktion gesendet haben. Und das ist vom Typ Float. Und wenn wir dann mit Center
einen Wert erhalten, wir die
gerundete Version davon zurück, die eine Ganzzahl ist, und dann die letzte, das ist der Rückgabewert. Sie können also tatsächlich
Rendite und Rendite in
einem Generator kombinieren , und
dann
endet die Funktion und
sie wird zurückkehren. Okay? Wenn ich das ausführe,
können Sie sehen, dass ich
hier eine Hauptfunktion habe , bei der
ich diese Funktion aufrufe als nächste. Und dann sende ich
diese Werte dorthin. Und dann kannst du sehen, dass es diese
Dinge
durchmacht und es endet mit, okay, so
funktioniert es im Grunde. Also ein anderer
Anwendungsfall dafür. Nun, nicht so viele, um ehrlich zu sein, vielleicht
hast du einen, aber ich bin nie auf
eine Situation gestoßen , in der ich das benutzen
musste. Seien Sie auch vorsichtig, wenn Sie Renditen und Renditen
kombinieren. Auf diese Weise
verkompliziert es meiner Meinung nach das Goldene und macht es schwieriger zu verstehen,
was tatsächlich passiert.
21. Generatoren 3/4: Als Nächstes
möchte ich Ihnen
sogenannte
Generatorausdrücke zeigen . Und das ist auch sehr mächtig. Auf diese Weise können Sie einen
Ausdruck erstellen, der eigentlich
ein Generator ist , und Sie geben die Berechnung sofort
innerhalb des Ausdrucks an. Es ist ein bisschen wie
Lambda-Funktionen, anonyme Funktionen, aber dann sind
es anonyme Generatoren. Sie sehen hier ein Beispiel. Ich habe einen Stromgenerator, der CC ist. Wenn ich den Mauszeiger über diesen Wert bewege, ist es eigentlich
ein Generator, aber amüsant und ein Ausdruck
hier in Klammern, das ist der Generatorausdruck. Und
der Ausdruck ist zwei hoch von I für
I in einem Bereich von zehn. Es ist also ein endlicher Generator. Und dann verwende ich eine For-Schleife, um über diesen
Potenzgenerator zu iterieren und dann
die Wertgeneratoren so zu drucken ,
wie Ints oder Floats oder Funktionen Objekte sind, die Sie an andere
Funktionen übergeben können, z. B. akzeptiert
die Summenfunktion einen Generator und somit auch
einen Generatorausdruck. Sie können also sehr
einfach die Summe
all dieser Dinge erstellen , indem sie
einfach an
die Summenfunktion übergeben. Also, wenn ich das ausführe, dann
bekommen wir das. Die Summe ist 1023. Generatorausdrücke sind
auch sehr mächtig, weil sie solche
Berechnungen ermöglichen, sie
aber nur dann ausführen, wenn Sie
tatsächlich Werte benötigen. Das ist also etwas anderes als, sagen
wir, ein Listenverständnis. Wenn ich diese
Parameter durch eckige Klammern ändern würde, hätten wir ein
Listenverständnis. Sie können auch darüber iterieren, aber das
Listenverständnis wird
bereits berechnet , wenn Sie es
als diesen Generator definieren. Das wird also faul gemacht, was wirklich hilfreich ist, wenn Sie etwas
Rechenzeit sparen
möchten.
22. Generatoren 4/4: Eine weitere schöne
Sache an Generatoren ist, dass sie sich
gut in gleichzeitigen Code integrieren lassen. Das ist alles eine der
vorherigen Lektionen denen
ich über Async,
IO und gleichzeitigen Code gesprochen habe . Nun, eigentlich können Sie auch asynchrone
Gleichzeitigkeitsgeneratoren
haben. Hier ist ein Beispiel. Ich
habe hier eine Funktion. Es ist eine asynchrone
Funktion, die einen zufälligen Pokémon-Namen
erhält. Es basiert also auf dem
Async-IO-Beispiel, das ich zuvor verwendet habe. Und das gibt einfach
den Namen des Pokémon zurück. Und dann habe ich hier eine
Generatorfunktion,
die nach
der Summe nächstes Pokemon heißt. Dann mache ich eine Runde,
in der ich die Gesamtsumme
durchgehe und jedes Mal verwende
ich ein Gewicht, um
den zufälligen Pokémon-Namen zu erhalten , und
dann gebe ich diesen Namen ab. Du kannst auch Yield Away Away fahren. Sie
müssen hier also nicht variieren. Aber wie Sie sehen können, lässt
es sich sehr gut
in asynchronen Code integrieren. Sie schreiben einfach async
davor und Sie können ein Gewicht in Ihrem Generator
verwenden, und dann wird
es gleichzeitig sein. Der Typ ist jedoch anders. Es gibt einen Async, der
einen Typ generiert, wie Sie ihn hier sehen. Aber im Prinzip ist
die Idee, dass es genauso
funktioniert. Und wenn Sie dann
in der Hauptfunktion nachschauen, die ebenfalls synchron ist, haben
wir eine asynchrone
For-Schleife, die
den nächsten Pokémon-Generator durchläuft den nächsten Pokémon-Generator und die
nächsten Pokémon-Namen erhält. Und Sie können
asynchrone Generatoren
auf verschiedene Arten
und Python verwenden , z. B. hier habe ich ein
Listenverständnis,
das den nächsten asynchronen Pokemon-Generator
verwendet . Und dann verwende ich ein
asynchrones Listenverständnis , um all diese Daten zu erhalten. Wenn ich das also ausführe, wirst du
sehen, dass es jetzt
diese API-Aufrufe durchläuft und
all diese Pokémon-Namen erhält. Das sammelt nicht
alle Antworten weil es ein
Generator ist, also ist es faul. Es wird den
Befehl nur ausführen, wenn Sie danach fragen. Deshalb sehen wir, dass sie eins nach dem anderen
erscheinen. Aber das bedeutet
, dass, wenn Sie nur fünf weitere Namen
benötigen diese
nur
fünfmal aufrufen und das nur fünf API-Anforderungen. Anstatt alle
API-Anfragen zu erledigen und dann
nur fünf Werte zu verwenden. Das ist ein Unterschied zwischen
den Generatortyphinweisen und
dem asynchronen Generieren eines Typs. Und das
musste ich tatsächlich
vor einer Minute korrigieren, weil es
falsch war, weil das async generierte nicht
den Typ für
den Rückgabewert hat
, weil das
mit asynchron nicht möglich ist, wir haben nur Erträge. Deshalb hat es nur zwei
Argumente statt drei. Aber auch das ist
nicht etwas, das Sie normalerweise häufig
in Ihrem Code verwenden
würden. Warum ist das also nützlich? Nun, es gibt eine einfache Möglichkeit, Iteratoren zu
erstellen,
ohne eine Klasse mit den Methoden
iter und next dunder erstellen zu müssen. Sie lassen sich natürlich auch gut in Kinder
oder Tools
integrieren ,
über die in der vorherigen Lektion gesprochen wurde. Sie sind speichereffizient und
vermeiden überflüssige Berechnungen. Wenn Sie den Wert nicht anfordern, wird er nicht berechnet. Und im Allgemeinen ist es eine großartige
Möglichkeit,
Datenströme über ein Netzwerk darzustellen . Jedes Mal, wenn Sie das
nächste Objekt aus
dem Netzwerk abrufen, sollten Sie auf einige Dinge achten
, dass
Generatoren zu
einer
Schicht führen können, die schwieriger
zu verstehen ist Generatoren zu
einer
Schicht führen können, die schwieriger
zu ,
insbesondere wenn Sie anfangen, Rendite- und Renditeabrechnungen in
einem einzigen Generator zu
kombinieren . Und zweitens, da der
Code nur auf Anfrage ausgeführt wird, ist es möglich, dass Sie erst nach einer
Weile auf einen Fehler
stoßen , der zu
einer unerwarteten
Box und später führen kann , sodass Sie
sicherstellen müssen, dass Sie sie
tatsächlich richtig testen. Insgesamt
sind Generatoren also ein wirklich nettes Tool, sie werden
vielleicht nicht ständig verwendet, aber in einigen Fällen
sind sie wirklich nützlich. Lassen Sie uns nun zur
letzten Lektion über
Kontext-Manager übergehen .
23. Context Manager 1/4: Die letzte Python-Funktion, die ich in diesem Kurs behandeln
möchte ist der sogenannte
Kontextmanager. Und das baut auf anderen Funktionen auf, über die
ich in
den vorherigen Lektionen gesprochen habe , wie
Iteratoren und Generatoren. Und es ist auch kompatibel
mit asynchronem Code, wie ich Ihnen in
einer Minute zeigen werde. Kontexte, Manager sind wirklich
nützlich, weil Sie damit
kontrollieren können, was passiert wenn Sie Ressourcen erstellen oder zerstören
, abbauen. Und Sie können sicherstellen, dass Sie z. B. einen
Kontextmanager verwenden können, um zu kontrollieren, was passiert, um eine Ressource freizugeben,
wenn es beispielsweise eine Ausnahme gibt
oder wenn es einen
anderen Grund gibt, warum das Programm aufhören
muss, das
zu tun das Programm aufhören
muss ,
was passiert. Und das ist nützlich, z. B. wenn Sie eine Datei schließen müssen, wenn Sie
die Datenbankverbindung schließen müssen da Sie einer
anderen Oberfläche mitteilen müssen, dass Ihre Anwendung
eine Aufgabe stoppt und Sie
sicherstellen möchten, dass das immer passiert. Hier sind
Kontext-Manager wirklich nützlich. In einer der vorherigen
Lektionen habe ich Ihnen gezeigt, wie Sie eine Datei mit
der Width-Anweisung
öffnen. Das ist eigentlich ein Beispiel
für einen Kontextmanager. Und der Grund, warum wir dort eine
Width-Anweisung verwenden, ist, dass sie es der Context
Manager-Datei,
Context Manager, ermöglicht , sich selbst
ordnungsgemäß zu schließen , nachdem Sie den Inhalt
gelesen haben. Und
wieder gibt es zwei
Dahmer-Methoden, die wichtig sind. Es gibt die dominierenden Methoden Enter und
Exit. Enter ist der Ort, an dem Sie alles ablegen ,
was
passieren muss, wenn Sie
eine Ressource erstellen , und beenden Sie
es, wenn Sie die Ressource
zerstören müssen.
24. Context Manager 2/4: Hier sehen Sie ein weiteres Beispiel
für die Verwendung eines Kontextmanagers. Ich verwende
hier SQL Lite Three, das stellt eine Verbindung zu einer Datenbank her, die
nur eine lokale Datei ist. Und dann wähle ich Elemente
aus einer Tabelle mit Blöcken aus. Und Sie sehen, dass
wir hier einfach
eine Verbindung mit
SQLite Dot Connects herstellen , aber Sie können
dies tatsächlich als Kontextmanager verwenden. Wenn ich diesen Code
ausführe, sehen wir das. Sie sehen also, wir bekommen im Grunde eine Liste
von Blogs. Aber die Sache ist, dass wir
sicherstellen müssen , dass wir die Verbindung immer schließen, oder? Das ist es also, was hier passiert. Deshalb ist dies
kein Versuch, endlich zu blockieren. Also wenn ich hier z.B. einen Tippfehler mache, so bloggt das nicht. Wir werden also eine
Art von Fehler bekommen, der nicht in der Tabelle angezeigt wird. Dadurch wird immer noch sichergestellt, dass die Verbindung
ordnungsgemäß geschlossen ist. Wenn Sie nun vermeiden möchten, dies schreiben
zu müssen , versuchen Sie es endlich Sie
können auch sqlite dot
connect als Kontextmanager verwenden . Also
schreiben wir einfach width sqlite dot connect als Sammlung. Und dann muss ich das
natürlich
einrücken und es
sollte hier eine Kolumne geben. Was ich jetzt tun kann, ist dasselbe zu
tun, die Blogs
auszudrucken, aber dann kann
ich einen Fehler eingeben. Aber das einzige
ist, dass Sie jetzt im Protokoll sehen
können, dass
die Verbindung dadurch nicht richtig
geschlossen wird . Dies wird hauptsächlich verwendet, um Transaktionen in der Datenbank rückgängig zu
machen und solche Dinge. Das Schöne an Python
ist also, dass wir tatsächlich unsere eigenen
Kontext-Manager
erstellen können . Wir müssen nur
eine Klasse mit
einer Enter- und Exit-Dunder-Methode bereitstellen und diese dann stattdessen verwenden. Sie sehen also ein Beispiel dafür. Ich habe eine Klasse sqlite erstellt. Ich gebe ihm
den Dateinamen, das ist
also die Anwendung von TB. Und ich speichere eine
neue Verbindung, um eine Verbindung zur Datenbank
in der Enter-Methode Dann erhalte
ich den Cursor
und dann den Exit. Ich übernehme die Änderungen nicht und schließe dann die Verbindung. Also in unserer Hauptfunktion haben
wir dann mit SQL Light. Also verwende ich jetzt diesen
Kontextmanager hier, und das gibt mir
den Cursor und dann kann ich meine Abfrage
ausführen und das Ergebnis
zurückgeben. Also, wenn ich das durchführe, werden
wir wieder genau die
gleichen Ergebnisse erzielen, oder? Wir werden diese Blogs drucken, aber dann heißt es Answer und
Exit , wenn es fertig ist. Wir sind uns also sicher, dass die Verbindung
immer geschlossen ist , weil ich jetzt zB hier
nochmal einen Fehler vorstellen möchte. Wenn ich das noch einmal starte, siehst
du, dass es tatsächlich immer noch Enter und Exit aufgerufen
hat. Der Kontextmanager hat die Verbindung ordnungsgemäß
geschlossen, auch wenn ein Fehler auftritt.
25. Context Manager 3/4: Anstatt dieser Klasse
mit den Enter- und Exit-Methoden
können Sie nun auch einen
Decorator verwenden, der auf der generierten
Funktion
basiert, über die in der vorherigen Lektion gesprochen wurde. So sieht das also aus. Ich importiere den Context
Manager Decorator aus Contexts Live und amüsiere das hier,
um darauf hinzuweisen, dass diese Funktion ein Kontextmanager sein wird
. Und dann siehst du, dass ich
eine Generatorstruktur mit
Yield verwende , um tatsächlich zu
definieren, was in den Antworten
und Exit-Teilen
passieren soll . Es funktioniert also so
, dass alles, was vor Erträge liegt,
die Eingabeteile sind. Alles danach
ist der Ausgangsteil. Das ist also, das ist im Grunde das,
was Sie hier sehen. Und das hat genau den gleichen
Effekt wie die Verwendung einer Klasse. Oder wenn ich das starte,
siehst du, dass wir hier
eine Verbindung schließen und eine Verbindung
herstellen und
wir drucken die Blogs. Wenn ich hier wieder entferne, lassen Sie uns einfach zum Spaß einen anderen
Charakter entfernen. Und dann lassen Sie uns das noch einmal ausführen. Sie sehen, dieser Fehler wird immer noch angezeigt, aber jetzt wird die
Verbindung immer noch ordnungsgemäß geschlossen, da wir einen
Kontextmanager, Decorator, verwenden.
26. Context Manager 4/4: Letzte Sache, die ich Ihnen zeigen
möchte, ist, dass Kontextmanager auch die asynchrone
und wartende Syntax der
Integration mit
gleichzeitigem Code
unterstützen und wartende Syntax der ,
genau wie Generatoren,
wenn sie einen asynchronen
Kontextmanager
gewähren möchte, den asynchronen Context genau wie Generatoren,
wenn sie einen asynchronen
Kontextmanager
gewähren möchte , den asynchronen Manager-Decorator
verwendet haben. Jetzt gibt es hier einige
Tippprobleme, da dies eher ein grobes Beispiel
ist. Die Idee ist jedoch, dass Sie in diesem Fall einen
Asynchrongenerator anstelle
eines regulären Synchrongenerators
verwenden Asynchrongenerator anstelle
eines . Kontext-Manager arbeiten also auch
in diesem Sinne. Also z. B. hier, nehmen wir an, Sie haben eine asynchrone Datenbankschicht. Sie können die asynchrone
Await-Syntax verwenden, um hierher zu gelangen, z. B. eine
Datenbankverbindung, wir
verwenden die Verbindung und Releasing ist ebenfalls asynchron und wir stellen Async davor. Und dann kannst du das
im Rest deines Codes verwenden, wie ich es hier mache, zB ich bekomme alle Benutzer. Sql Light selbst ist
nicht asynchron, aber es gibt ein Paket
namens sclerites, das
asynchron ist und mit dem Sie asynchron
auf eine SQL
Light-Datenbank zugreifen können . Sie sehen ein einfaches Beispiel dafür
, wie das funktioniert. Also habe ich statt
SQLite Dot Connect, das tue
ich, ich alle SQLite Dot Connect. Aber das ist asynchron, verwendet aber immer noch die
Width-Anweisungen. Und Sie tun
dasselbe, um
einen Cursor dazu zu bringen , alle
Daten aus der Tabelle abzurufen. Also, wenn Sie das verwenden, nun, die wichtigsten Stellen, an denen Sie
sicherstellen müssen, dass Sie ordnungsgemäß schließen oder
aufräumen Ihr Chaos
ordnungsgemäß schließen oder
aufräumen, auch wenn
etwas schief geht. Und das ist insbesondere bei
Datenbanken
der Fall , in denen wir Verbindungen
verfolgen. Oder Sie möchten sicherstellen, dass
Sie diese Verbindung schließen. Oder vielleicht müssen Sie
einem API-Knoten mitteilen , dass Sie einen Prozess
abgeschlossen haben Sie möchten sicherstellen
, dass dieser
Abschlussaufruf auch dann stattfindet,
wenn eine Ausnahme auftritt . Und hier sind
Kontextmanager wirklich nützlich. Und schließlich ist
es aus Sicht des
Softwaredesigns wirklich nett, dass
Sie die Erstellung und
Zerstörung von Ressourcen
an einem einzigen Ort gruppieren können .
27. Wir kommen zum Ende.: Vielen Dank, dass Sie diesen Kurs besucht haben. Ich hoffe, es hat Ihnen einige
Denkanstöße gegeben und Ihnen einige Ideen gegeben, wie Sie
Ihren vorhandenen Python-Code verbessern können. Ich hatte viel Spaß beim
Aufnehmen dieses Kurses, aber es gibt natürlich noch eine Menge anderer Dinge, in die wir eintauchen könnten. Ein bisschen mehr über Python, insbesondere über
Softwaredesign, wie ich
am Anfang erwähnt habe, schau dir meinen YouTube-Kanal an, youtube.com slash ion codes. Wenn du Fragen oder
Anregungen hast ,
schreib einfach hier einen Kommentar. Ich würde mich freuen,
von dir zu hören. Danke fürs Zuschauen und pass auf dich auf.