Bild vom Autor
Schreiben von effizientem Python-Code ist wichtig für die Optimierung der Leistung und Ressourcennutzung, unabhängig davon, ob Sie an Knowledge-Science-Projekten arbeiten, Net-Apps erstellen oder andere Programmieraufgaben erledigen.
Durch die Verwendung der leistungsstarken Funktionen und Greatest Practices von Python können Sie die Rechenzeit verkürzen und die Reaktionsfähigkeit und Wartbarkeit Ihrer Anwendungen verbessern.
In diesem Tutorial zeigen wir Ihnen fünf wichtige Tipps, die Ihnen dabei helfen, effizienteren Python-Code zu schreiben. Dazu geben wir Ihnen Codebeispiele. Legen wir los.
1. Verwenden Sie Listenverständnisse anstelle von Schleifen
Sie können Listenverständnisse verwenden, um Pay attention aus vorhandenen Pay attention und anderen Iterablen wie Zeichenfolgen und Tupeln zu erstellen. Sie sind im Allgemeinen prägnanter und schneller als normale Schleifen für Listenoperationen.
Nehmen wir an, wir haben einen Datensatz mit Benutzerinformationen und möchten die Namen der Benutzer extrahieren, die einen Rating über 85 haben.
Verwenden einer Schleife
Lassen Sie uns dies zunächst mit einer For-Schleife und einer If-Anweisung tun:
information = ({'identify': 'Alice', 'age': 25, 'rating': 90},
{'identify': 'Bob', 'age': 30, 'rating': 85},
{'identify': 'Charlie', 'age': 22, 'rating': 95})
# Utilizing a loop
consequence = ()
for row in information:
if row('rating') > 85:
consequence.append(row('identify'))
print(consequence)
Sie sollten die folgende Ausgabe erhalten:
Output >>> ('Alice', 'Charlie')
Verwenden einer Listenableitung
Lassen Sie uns nun mit einer Listenableitung neu schreiben. Sie können die generische Syntax verwenden (output for enter in iterable if situation)
etwa so:
information = ({'identify': 'Alice', 'age': 25, 'rating': 90},
{'identify': 'Bob', 'age': 30, 'rating': 85},
{'identify': 'Charlie', 'age': 22, 'rating': 95})
# Utilizing a listing comprehension
consequence = (row('identify') for row in information if row('rating') > 85)
print(consequence)
Das sollte zur gleichen Ausgabe führen:
Output >>> ('Alice', 'Charlie')
Wie man sieht, ist die Listing-Comprehension-Model prägnanter und einfacher zu warten. Sie können andere Beispiele ausprobieren und Profilieren Sie Ihren Code mit timeit, um die Ausführungszeiten von Schleifen und Listenverständnissen zu vergleichen.
Mit Listenverständnissen können Sie daher lesbareren und effizienteren Python-Code schreiben, insbesondere bei der Transformation von Pay attention und Filteroperationen. Aber seien Sie vorsichtig, dass Sie sie nicht überbeanspruchen. Lesen Sie Warum Sie Listenverständnisse in Python nicht übermäßig verwenden sollten um zu erfahren, warum ein übermäßiger Gebrauch des Guten zu viel sein kann.
2. Verwenden Sie Generatoren zur effizienten Datenverarbeitung
Sie können Generatoren in Python verwenden, um über große Datensätze und Sequenzen zu iterieren, ohne sie alle im Voraus im Speicher abzulegen. Dies ist besonders nützlich bei Anwendungen, bei denen Speichereffizienz wichtig ist.
Im Gegensatz zu regulären Python-Funktionen, die den return
Schlüsselwort, um die gesamte Sequenz zurückzugeben. Generatorfunktionen liefern ein Generatorobjekt. Über das Sie dann eine Schleife durchführen können, um die einzelnen Elemente abzurufen – bei Bedarf und einzeln.
Angenommen, wir haben eine große CSV-Datei mit Benutzerdaten und möchten jede Zeile einzeln verarbeiten, ohne die gesamte Datei auf einmal in den Speicher zu laden.
Hier ist die Generatorfunktion hierfür:
import csv
from typing import Generator, Dict
def read_large_csv_with_generator(file_path: str) -> Generator(Dict(str, str), None, None):
with open(file_path, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
yield row
# Path to a pattern CSV file
file_path="large_data.csv"
for row in read_large_csv_with_generator(file_path):
print(row)
Notiz: Denken Sie daran, im obigen Snippet „large_data.csv“ durch den Pfad zu Ihrer Datei zu ersetzen.
Wie Sie bereits sehen, ist die Verwendung von Generatoren besonders hilfreich, wenn Sie mit Streaming-Daten arbeiten oder wenn die Datensatzgröße den verfügbaren Speicher überschreitet.
Eine ausführlichere Übersicht über Generatoren finden Sie unter Erste Schritte mit Python-Generatoren.
3. Teure Funktionsaufrufe zwischenspeichern
Durch das Caching kann die Leistung erheblich verbessert werden, indem die Ergebnisse aufwändiger Funktionsaufrufe gespeichert und wiederverwendet werden, wenn die Funktion erneut mit denselben Eingaben aufgerufen wird.
Angenommen, Sie programmieren den Okay-Means-Clusteralgorithmus von Grund auf neu und möchten die berechneten euklidischen Distanzen zwischenspeichern. So können Sie Funktionsaufrufe zwischenspeichern mit dem @cache
Dekorateur:
from functools import cache
from typing import Tuple
import numpy as np
@cache
def euclidean_distance(pt1: Tuple(float, float), pt2: Tuple(float, float)) -> float:
return np.sqrt((pt1(0) - pt2(0)) ** 2 + (pt1(1) - pt2(1)) ** 2)
def assign_clusters(information: np.ndarray, centroids: np.ndarray) -> np.ndarray:
clusters = np.zeros(information.form(0))
for i, level in enumerate(information):
distances = (euclidean_distance(tuple(level), tuple(centroid)) for centroid in centroids)
clusters(i) = np.argmin(distances)
return clusters
Betrachten wir den folgenden Beispielfunktionsaufruf:
information = np.array(((1.0, 2.0), (2.0, 3.0), (3.0, 4.0), (8.0, 9.0), (9.0, 10.0)))
centroids = np.array(((2.0, 3.0), (8.0, 9.0)))
print(assign_clusters(information, centroids))
Welche Ausgaben:
Outputs >>> (0. 0. 0. 1. 1.)
Weitere Informationen finden Sie unter So beschleunigen Sie Python-Code durch Caching.
4. Verwenden Sie Kontextmanager für die Ressourcenverwaltung
In Python Kontextmanager Stellen Sie sicher, dass Ressourcen wie Dateien, Datenbankverbindungen und Unterprozesse nach der Verwendung ordnungsgemäß verwaltet werden.
Angenommen, Sie müssen eine Datenbank abfragen und möchten sicherstellen, dass die Verbindung nach der Verwendung ordnungsgemäß geschlossen wird:
import sqlite3
def query_db(db_path):
with sqlite3.join(db_path) as conn:
cursor = conn.cursor()
cursor.execute(question)
for row in cursor.fetchall():
yield row
Sie können jetzt versuchen, Abfragen an die Datenbank auszuführen:
question = "SELECT * FROM customers"
for row in query_database('individuals.db', question):
print(row)
Weitere Informationen zur Verwendung von Kontextmanagern finden Sie unter 3 interessante Verwendungsmöglichkeiten für Pythons Kontextmanager.
5. Vektorisierungsoperationen mit NumPy
Mit NumPy können Sie elementweise Operationen an Arrays durchführen – wie Operationen an Vektoren – ohne dass explizite Schleifen erforderlich sind. Dies ist oft deutlich schneller als Schleifen, da NumPy im Hintergrund C verwendet.
Angenommen, wir haben zwei große Arrays, die Ergebnisse aus zwei verschiedenen Assessments darstellen, und wir möchten die Durchschnittsnote für jeden Schüler berechnen. Lassen Sie uns dies mithilfe einer Schleife tun:
import numpy as np
# Pattern information
scores_test1 = np.random.randint(0, 100, measurement=1000000)
scores_test2 = np.random.randint(0, 100, measurement=1000000)
# Utilizing a loop
average_scores_loop = ()
for i in vary(len(scores_test1)):
average_scores_loop.append((scores_test1(i) + scores_test2(i)) / 2)
print(average_scores_loop(:10))
So können Sie sie mit den vektorisierten Operationen von NumPy umschreiben:
# Utilizing NumPy vectorized operations
average_scores_vectorized = (scores_test1 + scores_test2) / 2
print(average_scores_vectorized(:10))
Schleifen vs. vektorisierte Operationen
Lassen Sie uns die Ausführungszeiten der Schleife und der NumPy-Versionen mit timeit messen:
setup = """
import numpy as np
scores_test1 = np.random.randint(0, 100, measurement=1000000)
scores_test2 = np.random.randint(0, 100, measurement=1000000)
"""
loop_code = """
average_scores_loop = ()
for i in vary(len(scores_test1)):
average_scores_loop.append((scores_test1(i) + scores_test2(i)) / 2)
"""
vectorized_code = """
average_scores_vectorized = (scores_test1 + scores_test2) / 2
"""
loop_time = timeit.timeit(stmt=loop_code, setup=setup, quantity=10)
vectorized_time = timeit.timeit(stmt=vectorized_code, setup=setup, quantity=10)
print(f"Loop time: {loop_time:.6f} seconds")
print(f"Vectorized time: {vectorized_time:.6f} seconds")
Wie man sieht, sind vektorisierte Operationen mit Numpy viel schneller als die Schleifenversion:
Output >>>
Loop time: 4.212010 seconds
Vectorized time: 0.047994 seconds
Einpacken
Das ist alles für dieses Tutorial!
Wir haben die folgenden Tipps überprüft – Verwenden von Listenverständnissen statt Schleifen, Ausnutzung von Generatoren für eine effiziente Verarbeitung, Zwischenspeichern teurer Funktionsaufrufe, Verwalten von Ressourcen mit Kontextmanagern und Vektorisieren von Operationen mit NumPy – die Ihnen dabei helfen können, die Leistung Ihres Codes zu optimieren.
Wenn Sie nach Tipps speziell für Knowledge Science-Projekte suchen, lesen Sie 5 Python Greatest Practices für Knowledge Science.
Bala Priya C ist Entwicklerin und technische Redakteurin aus Indien. Sie arbeitet gerne an der Schnittstelle zwischen Mathematik, Programmierung, Datenwissenschaft und Inhaltserstellung. Ihre Interessens- und Fachgebiete umfassen DevOps, Datenwissenschaft und Verarbeitung natürlicher Sprache. Sie liest, schreibt, programmiert und trinkt gerne Kaffee! Derzeit arbeitet sie daran, ihr Wissen zu lernen und mit der Entwickler-Neighborhood zu teilen, indem sie Tutorials, Anleitungen, Meinungsbeiträge und mehr verfasst. Bala erstellt auch ansprechende Ressourcenübersichten und Programmier-Tutorials.