Python: Werde Python Experte | ArjanCodes | Skillshare
Suchen

Playback-Geschwindigkeit


1.0x


  • 0.5x
  • 0.75x
  • 1x (normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Einheiten dieses Kurses

    • 1.

      Klassenübersicht: Was du lernen wirst

      1:02

    • 2.

      Wie unterschiedliche Programmiersprachen mit Typen umgehen

      7:25

    • 3.

      Tippe Anmerkungen in Python: Basic bis Advanced

      4:21

    • 4.

      Duck mit Protocol

      5:28

    • 5.

      Wie Dataclasses dir dabei helfen, bessere Kurse zu schreiben

      10:56

    • 6.

      Freischaltung der Leistung von Klasseneigenschaften

      4:44

    • 7.

      Was ist der Unterschied zwischen Str und Unternehmer?

      2:33

    • 8.

      Wie man die Leistung von Mitgliedern des Accessing verbessert

      3:17

    • 9.

      Callables und Funktionen

      5:29

    • 10.

      Partial

      3:10

    • 11.

      Cached Properties

      2:01

    • 12.

      Einzelner Versand

      2:58

    • 13.

      Was ist die gleichzeitige Programmierung?

      4:07

    • 14.

      Async, warten und sammeln

      5:21

    • 15.

      So verwandle man einen nicht gleichzeitigen Code in einen gleichzeitigen Code.

      3:46

    • 16.

      Iteratoren und Iterables: die Grundlagen

      5:44

    • 17.

      Verwendung von Iteratoren zur Einführung von Abstraktion

      1:20

    • 18.

      Itertools: Ein Iterator Algebra auf einem nächsten Level

      7:27

    • 19.

      Generatoren aka Lazy Interators

      1:39

    • 20.

      Generatorfunktionen, Ertrag und Rückkehr

      2:18

    • 21.

      Generator

      1:42

    • 22.

      Generatoren und Concurrency

      3:39

    • 23.

      Was ist ein Context Manager?

      1:32

    • 24.

      Context Manager Class

      2:33

    • 25.

      Context Manager Decorator (Viel einfacher!)

      1:10

    • 26.

      Context Manager und Concurrency

      1:58

    • 27.

      Wir kommen zum Ende.

      0:30

  • --
  • Anfänger-Niveau
  • Fortgeschrittenes Niveau
  • Fortgeschrittenes Niveau
  • Jedes Niveau

Von der Community generiert

Das Niveau wird anhand der mehrheitlichen Meinung der Teilnehmer:innen bestimmt, die diesen Kurs bewertet haben. Bis das Feedback von mindestens 5 Teilnehmer:innen eingegangen ist, wird die Empfehlung der Kursleiter:innen angezeigt.

718

Teilnehmer:innen

2

Projekte

Über diesen Kurs

Willst du dein Wissen über Python erweitern und deine Codierungsfähigkeiten auf ein neues Level heben? Wenn ja, ist dieser Kurs für dich da! Dieser Kurs gibt dir ein tieferes Verständnis von Python und ermöglicht dir, besseren Code viel schneller zu schreiben.

Dieser Kurs ist kuratiert und enthält die Themen, die ich denke, werden die günstigsten für dich sein, wenn du bei Python besser werden willst.

Das lernst du:

  • Welche Art Anmerkungen sind und warum es wichtig ist, dass du sie verwendest.
  • Erweiterte Nutzung von Klassen einschließlich Dataclasses, Eigenschaften und mehr
  • Erweiterte funktionale Programmierung mit Lambda-Funktionen, partielle Funktionsanwendung und mehr
  • Gleichzeitige Programmiertechniken zur Optimierung des Interagierens Ihres Codes mit APIs
  • Erweiterte Steuerlogik mit Iteratoren und Generatoren
  • Und vieles mehr!

Egal, ob du vor allem Python zum Bearbeiten und Analysieren von Daten verwendest, oder Python zum Erstellen komplexer Softwareanwendungen wie APIs benutzt, du wirst diesen Kurs wirklich genießen und ein wahrer Python werden.

Also, wenn du bereit bist - lass uns eintauchen!

Triff deine:n Kursleiter:in

Teacher Profile Image

ArjanCodes

Become a Better Software Developer

Kursleiter:in

Hi there!

I'm Arjan - I'm a YouTuber, entrepreneur and online teacher. I've completed both a Master and PhD in Computer Science and I've been a university teacher for over 20 years, I've launched several and designed and built complete software products from scratch.

On my YouTube channel ArjanCodes I teach software design, development and testing - specifically in Python. A lot of people are learning how to code in Python. They often start with writi... Vollständiges Profil ansehen

Skills dieses Kurses

Entwicklung Programmiersprachen Python
Level: Intermediate

Kursbewertung

Erwartungen erfüllt?
    Voll und ganz!
  • 0%
  • Ja
  • 0%
  • Teils teils
  • 0%
  • Eher nicht
  • 0%

Warum lohnt sich eine Mitgliedschaft bei Skillshare?

Nimm an prämierten Skillshare Original-Kursen teil

Jeder Kurs setzt sich aus kurzen Einheiten und praktischen Übungsprojekten zusammen

Mit deiner Mitgliedschaft unterstützt du die Kursleiter:innen auf Skillshare

Lerne von überall aus

Ob auf dem Weg zur Arbeit, zur Uni oder im Flieger - streame oder lade Kurse herunter mit der Skillshare-App und lerne, wo auch immer du möchtest.

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.