Heim > Artikel > Backend-Entwicklung > So schreiben Sie effizienten Python-Code
Dieser Artikel stellt hauptsächlich vor und teilt, wie man effizienten und eleganten Python-Code schreibt. Freunde, die ihn benötigen, können darauf verweisen
Dieser Artikel ist teilweise aus dem Buch „Effective Python“ und „Python3 Cookbook“ entnommen. Es wurden jedoch auch Änderungen vorgenommen und das eigene Verständnis und die Anwendung bewährter Methoden des Autors hinzugefügt.
Der vollständige Text umfasst etwa 9956 Wörter und das Lesen kann 24 Minuten dauern.
Pythonisches Listenschneiden
list[start:end:step]
Wenn Sie mit dem Schneiden am Anfang der Liste beginnen, ignorieren Sie die 0 im Startbit, z als list[:4]
Wenn Sie bis zum Ende der Liste ausschneiden, ignorieren Sie die 0 im Endbit. Beispiel: list[3:]
Wenn Sie die Liste ausschneiden, wird dies der Fall sein kein Problem sein, selbst wenn der Start- oder Endindex die Grenze überschreitet
Durch das Listen-Slicing wird die ursprüngliche Liste nicht geändert. Wenn alle Indizes leer bleiben, wird eine Kopie der ursprünglichen Liste generiert
Listenverständnisse
Verwenden Sie Listenverständnisse, um map
und filter
enumerate
Sie können den zweiten Parameter als Wert akzeptieren, der zu enumerate
hinzugefügt wird, wenn Sie index
um zwei Iteratoren gleichzeitig zu durchlaufen zip
Gibt beim Durchlaufen ein Tupel zurückzip
und for
while
Blöcke nach der Schleifeelse
ruft den Code in auf, nachdem sie normal beendet wurdeelse
zum Unterbrechen verwenden Außerhalb der Schleife wird break
else
else
übergeben, die eine umgekehrte Iteration durchführt: reversed()
in der Klasse implementieren: __reversed__
try/except/else/finally
keine Ausnahme auftritt, Der Code in try
wird else
in else
aufgerufen. Vor dem Ausführen von finally
ausgeführt, wo Sie die Funktion finally
Überwachunglog
ersetzt. Der Aufruf einer dekorierten Funktion entspricht dem Aufruf einer neuen Funktion. Beim Anzeigen der Parameter, Kommentare und sogar Funktionsnamen der Originalfunktion werden nur Informationen angezeigt, die sich auf den Dekorator beziehen. Um dieses Problem zu lösen, können wir die new_fun
-Methode verwenden. functools.wraps
ist eine sehr hackige Methode. Sie kann als Dekorator für die Funktion verwendet werden, die innerhalb des Dekorators zurückgegeben wird. Mit anderen Worten, es handelt sich um einen Dekorateur von Dekoratoren, der die ursprüngliche Funktion als Parameter verwendet. Seine Funktion besteht darin, verschiedene Informationen der ursprünglichen Funktion beizubehalten, sodass sie bei späterer Betrachtung der Informationen der dekorierten Originalfunktion genau erhalten bleiben können die gleiche wie die ursprüngliche funktion. functools.wraps
Darüber hinaus erledigt unser Dekorateur manchmal mehr als eine Aufgabe. In diesem Fall sollte die Veranstaltung als zusätzliche Funktion getrennt werden. Da es sich jedoch möglicherweise nur um den Dekorator handelt, kann zu diesem Zeitpunkt eine Dekoratorklasse erstellt werden. Das Prinzip ist sehr einfach, die Hauptsache ist, die Methode __call__
in die Klasse zu schreiben, damit die Klasse wie eine Funktion aufgerufen werden kann.
Verwenden Sie Generatoren
Erwägen Sie die Verwendung von Generatoren, um Funktionen neu zu schreiben, die Listen direkt zurückgeben
Bei dieser Methode gibt es mehrere kleine Probleme:
Jedes Mal, wenn ein Ergebnis erhalten wird, das die Bedingungen erfüllt, muss die Methode append
aufgerufen werden. Tatsächlich liegt unser Fokus jedoch überhaupt nicht auf dieser Methode, sie ist lediglich ein Mittel für uns, um unser Ziel zu erreichen. Tatsächlich müssen wir nur index
Die zurückgegebenen result
weiter optimieren
Die Daten werden in result
gespeichert. Wenn die Datenmenge groß ist, wird sie mehr Speicher beanspruchen
Daher ist es besser, den Generator generator
zu verwenden. Ein Generator ist eine Funktion, die einen yield
-Ausdruck verwendet. Wenn der Generator aufgerufen wird, wird er nicht tatsächlich ausgeführt, sondern gibt einen Iterator zurück. Jedes Mal, wenn die integrierte next
-Funktion für den Iterator aufgerufen wird Der Generator geht zum nächsten yield
-Ausdruck über:
Nachdem Sie einen Generator erhalten haben, können Sie ihn normal durchlaufen:
Wenn Sie noch eine Liste benötigen, können Sie das Ergebnis des Funktionsaufrufs als Parameter verwenden und dann die list
Methode
Iterierbares Objekt
aufrufen Es ist zu beachten, dass normale Iteratoren nur eine Runde lang iterieren können und wiederholte Aufrufe nach einer Runde ungültig sind. Der Weg, dieses Problem zu lösen, besteht darin, dass Sie eine iterierbare Containerklasse definieren können : Kein Problem:
Aber es sollte beachtet werden, dass es sich nur um eine handelt Iterator, der die
-Methode implementiert und nur durch die-Schleife iteriert werden kann, wenn Sie übergeben möchten. Für die Methodeniteration müssen Sie die
-Methode verwenden:__iter__
for
next
iter
Positionsparameter verwenden
Manchmal ist die Anzahl der von der Methode empfangenen Parameter möglicherweise nicht sicher, z. B. Definieren Sie eine Summierungsmethode, die mindestens zwei Parameter empfangen muss:
Für diese Art von Funktion, die nicht unbedingt eine bestimmte Anzahl von Parametern hat und sich nicht um die Reihenfolge kümmert, in der die Parameter übergeben werden, sollten Sie Positionsparameter
: Allerdings ist zu beachten, dass der Parameter variabler Länge *args
bei der Übergabe an die Funktion zunächst in ein Tupel
args
Schlüsselwortargumente verwenden tuple
Kann den Schlüsselwortparametern übergeben werden Geben Sie Standardwerte für Funktionen an
, um die Erweiterung von Funktionsparametern zu erleichtern
Definieren Sie Funktionen, die nur Schlüsselwortparameter verwenden könnenAuf die übliche Weise , beim Aufruf Die Verwendung von Schlüsselwortparametern wird nicht erzwungen, wenn
Die Methode zum Erzwingen von Schlüsselwortparametern in
Python3
Verwenden Sie die Methode zum Erzwingen von Schlüsselwortparametern in Python2
Über die Standardwerte von ParameternEs ist ein Klischee:
Der Standardwert einer Funktion wird nur einmal festgelegt, wenn das Programm das Modul lädt und die Definition der Funktion liest Mit anderen Worten, wenn es sich um einen dynamischen Wert handelt einem Parameter zugewiesen wird (Zum Beispieloder ), wenn den Parametern beim späteren Aufruf der Funktion andere Parameter zugewiesen werden, wenn diese Funktion in Zukunft erneut aufgerufen wird, die zuvor definierten Der Standardwert ändert sich und wird zum beim letzten Aufruf zugewiesenen Wert:
Daher wird eher empfohlen, None
als Standardparameter zu verwenden und den Wert nach der Beurteilung innerhalb der Funktion zuzuweisen:
Klasse__slots__
Standardmäßig verwendet Python ein Wörterbuch, um die Instanzattribute eines Objekts zu speichern. Dadurch können wir zur Laufzeit dynamisch neue Attribute zu Klasseninstanzen hinzufügen:
Dieses Wörterbuch verschwendet jedoch zusätzlichen Platz – oft werden wir es nicht erstellen. So viele Attribute. Mit __slots__
können Sie Python
also anweisen, kein Wörterbuch, sondern eine feste Sammlung zum Zuweisen von Speicherplatz zu verwenden.
__call__
Durch die Definition der __call__
-Methode in einer Klasse können Instanzen der Klasse wie gewöhnliche Funktionen aufgerufen werden.
Der Vorteil der Implementierung dieser Methode besteht darin, dass der Status über die Eigenschaften der Klasse gespeichert werden kann, ohne dass ein Abschluss oder eine globale Variable erstellt werden muss.
@classmethod
& @staticmethod
@classmethod
ist @staticmethod
sehr ähnlich, ihre Verwendungsszenarien sind jedoch unterschiedlich.
Gewöhnliche Methoden innerhalb der Klasse verwenden alle self
als ersten Parameter, was bedeutet, dass beim Aufruf über eine Instanz der Gültigkeitsbereich der Instanz an die Methode
@classmethod
übergeben wird Die Verwendung von cls
als ersten Parameter bedeutet, dass der Gültigkeitsbereich der Klasse selbst übergeben wird. Unabhängig davon, ob über eine Klasse oder eine Instanz einer Klasse aufgerufen wird, ist der erste standardmäßig übergebene Parameter die Klasse selbst
@staticmethod
Es ist nicht erforderlich, Standardparameter zu übergeben, ähnlich wie bei einer gewöhnlichen Funktion
Lassen Sie uns ihre Nutzungsszenarien anhand von Beispielen kennenlernen:
Angenommen, wir müssen eine Klasse mit dem Namen Date
erstellen, um drei Daten für Jahr/Monat/Tag zu speichern
Der obige Code erstellt die Date
-Klasse, die das day/month/year
-Attribut während der Initialisierung festlegt, und legt ein property
bis getter
fest, das über time
instanziiert werden kann. Holen Sie sich die gespeicherte Zeit:
Aber was ist, wenn wir die Art und Weise ändern möchten, wie die Eigenschaften übergeben werden? Schließlich ist es ärgerlich, bei der Initialisierung die drei Attribute Jahr/Monat/Tag übergeben zu müssen. Können Sie eine Möglichkeit finden, eine Instanz von 2016-11-09
zu erstellen, indem Sie eine Zeichenfolge wie Date
übergeben, ohne die vorhandene Schnittstelle und die vorhandenen Methoden zu ändern?
Sie könnten sich eine Methode wie diese vorstellen:
Aber sie ist nicht gut genug:
Schreiben Sie eine zusätzliche Methode außerhalb der Klasse. Jedes Mal müssen Sie die Parameter formatieren und dann abrufen.
Diese Methode bezieht sich nur auf die Date
-Klasse.
löst nicht das Problem, dass zu viele Parameter in
Sie können es zu diesem Zeitpunkt verwenden, eine neue Formatzeichenfolge innerhalb der Klasse erstellen und die Methode der Klasseninstanz zurückgeben: @classmethod
aufrufen. Die Methode Date
erstellt eine Instanz und greift nicht in die alte Instanziierungsmethode ein oder ändert sie nicht: from_string
können Sie @classmethod
Parameter übergeben und so den gleichen Komfort wie beim externen Aufrufen von Klassen erhaltencls
, da es einer gewöhnlichen Funktion ähnelt, können Sie die Hilfsmethode @staticmethod
in die Klasse einfügen und dann Rufen Sie diese Methode direkt über die Klasse auf. @staticmethod
-Methoden innerhalb der Klasse @staticmethod
platziert wurden, können diese Methoden über die Klasse aufgerufen werden: Date
-Anweisung erscheint häufig zusammen mit dem Kontextmanager. Zu den klassischen Szenarios gehören: with
Durch die with
-Anweisung schließt der Code den Dateiöffnungsvorgang ab und schließt die Datei automatisch, wenn der Aufruf endet oder während des Lesens eine Ausnahme auftritt, dh die Verarbeitung nach dem Lesen und Das Schreiben der Datei ist abgeschlossen. Wenn Sie den Kontextmanager nicht übergeben, sieht der Code wie folgt aus:
Ist das nicht umständlicher? Der Vorteil der Verwendung des Kontextmanagers besteht also darin, dass er uns automatisch dabei hilft, die Arbeit zu erledigen, wenn die Ausführung des Codeblocks beginnt und endet, indem er unsere voreingestellten Rückrufe aufruft. Mit den Methoden __enter__
und __exit__
der benutzerdefinierten Klasse können wir einen Kontextmanager anpassen.
kann dann so aufgerufen werden:
Beim Aufruf:
Das with
Die Anweisung speichert zunächst vorübergehend die ReadFile
-Methode __exit__
-Klasse und ruft dann die ReadFile
-Methode __enter__
der
__enter__
with
-Methode zum Öffnen auf die Datei und speichert das Ergebnis. Zurück zur
file_read
wird das Ergebnis des vorherigen Schritts an den
with
bearbeitet den file_read
-Parameter innerhalb von
with
Nachdem der Lesevorgang abgeschlossen ist, ruft die __exit__
-Anweisung die zuvor gespeicherte
__exit__
__exit__
Es ist zu beachten, dass wir in der True
-Methode Inside die Datei schließen, aber am Ende with
zurückgeben, sodass der Fehler nicht durch die with
-Anweisung ausgelöst wird. Andernfalls löst die
Das obige ist der detaillierte Inhalt vonSo schreiben Sie effizienten Python-Code. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!