Wir haben kürzlich eine
Übersetzung des Materials veröffentlicht, die nützliche Tipps für Python-Programmierer enthält. Dieses Material hat eine Fortsetzung, auf die wir Sie heute aufmerksam machen.

Slice-Benennung mit der Slice-Funktion
Das Arbeiten mit den vielen Werten, die in Indizes angegeben sind, kann schnell zu einem Durcheinander führen - sowohl in Bezug auf die Unterstützung als auch in Bezug auf die Lesbarkeit des Codes. Eine Möglichkeit, die Situation zu verbessern, besteht darin, Konstanten für die durch Indizes angegebenen Werte zu verwenden. Es gibt jedoch eine bessere Möglichkeit, Qualitätscode zu schreiben:
In diesem Beispiel können Sie sehen, dass wir die verwirrenden Indizes loswerden konnten, indem Sie den Slices mithilfe der
slice
Funktion Namen geben und diese Namen zum Abrufen der Fragmente der Zeichenfolge verwenden.
.start
.stop
zum
slice
Objekt erhalten Sie mit den
.start
,
.stop
und
.step
.
Anfordern eines Passworts vom Benutzer während der Programmausführung
Für viele Befehlszeilentools oder Skripts sind ein Benutzername und ein Kennwort erforderlich. Wenn Sie ein solches Programm schreiben müssen, ist das
getpass
Modul möglicherweise
getpass
:
import getpass user = getpass.getuser() password = getpass.getpass()
Mit diesem sehr einfachen Paket können Sie das Kennwort eines Benutzers anfordern und einen Benutzernamen erhalten, indem Sie den Namen abrufen, unter dem er angemeldet ist. Bei der Arbeit mit Kennwörtern sollten Sie jedoch beachten, dass nicht alle Systeme das Ausblenden von Kennwörtern unterstützen. Python wird versuchen, Sie zu benachrichtigen. In diesem Fall wird in der Befehlszeile eine entsprechende Warnung angezeigt.
Enge Übereinstimmungen in Zeichenfolgen finden
Lassen Sie uns nun über eine etwas mysteriösere Funktion der Python-Standardbibliothek sprechen. Angenommen, Sie befinden sich in einer Situation, in der Sie mithilfe eines Konzepts wie
Levenshtein distance nach Wörtern in der Liste suchen mussten, die wie eine bestimmte Eingabezeile aussehen. Dieses Problem kann mit dem
difflib
Modul gelöst werden.
import difflib difflib.get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'], n=2)
Die Methode
difflib.get_close_matches
nach den besten Übereinstimmungen, die „gut genug“ sind. Das erste Argument dieser Methode gibt die Suchzeichenfolge an, das zweite Argument gibt die Liste an, in der die Suche ausgeführt wird. Dieser Methode kann ein optionales Argument
n
, das die maximale Anzahl der zurückgegebenen Übereinstimmungen angibt. Diese Methode unterstützt auch den optionalen Grenzwert für benannte Argumente (standardmäßig ist er auf
0.6
), mit dem Sie einen Schwellenwert für die Bewertung von Übereinstimmungen festlegen können.
Mit IP-Adressen arbeiten
Wenn Sie Python-Programme für die Arbeit mit dem Netzwerk schreiben müssen, bedeutet dies, dass das
ipaddress
Modul für Sie sehr nützlich sein kann. Eine Möglichkeit besteht darin, eine Liste von IP-Adressen aus einem Adressbereich zu generieren, der im CIDR-Format (Classless Inter-Domain Routing, Classless Addressing) angegeben ist.
import ipaddress net = ipaddress.ip_network('74.125.227.0/29')
Eine weitere nützliche Funktion dieses Moduls ist die Überprüfung der IP-Adresse auf Zugehörigkeit zu einem bestimmten Netzwerk:
ip = ipaddress.ip_address("74.125.227.3") ip in net
Das
ipaddress
Modul hat viele andere interessante Funktionen, über die ich hier nicht spreche. Lesen Sie hier mehr über ihn. Beachten Sie bei der Verwendung dieses Moduls die Einschränkungen hinsichtlich der Zusammenarbeit mit anderen Modulen im Zusammenhang mit der Netzwerkprogrammierung. Beispielsweise können Sie
IPv4Network
Instanzen nicht als Adresszeichenfolgen verwenden. Ähnliche Objekte müssen dazu erst mit
str
in Strings konvertiert werden.
Debuggen eines Programms in der Befehlszeile
Wenn Sie zu denjenigen gehören, die die IDE nicht verwenden möchten und Code in Vim oder Emacs schreiben, müssen Sie möglicherweise einen Debugger wie den in der IDE ausführen. Und weißt du was? Sie haben bereits einen solchen Debugger. Führen Sie dazu einfach das Programm mit einer Struktur wie
python3.8 -i
. Mit dem Flag
-i
kann nach Abschluss des Programms eine interaktive Shell gestartet werden. Damit können Sie Variablen untersuchen und Funktionen aufrufen. Dies ist eine interessante Funktion, aber was ist mit einem echten Debugger (PDB)? Experimentieren wir mit dem folgenden einfachen Programm, dessen Code in der Datei
script.py
enthalten ist:
def func(): return 0 / 0 func()
Führen Sie es mit dem
python3.8 -i script.py
und erhalten Sie Folgendes:
Wir sehen den Ort des Programms, an dem der Absturz aufgetreten ist. Legen Sie einen Haltepunkt fest:
def func(): breakpoint()
Führen Sie das Skript erneut aus.
script.py(3)func()
-> return 0 / 0
(Pdb) #
(Pdb) step
ZeroDivisionError: division by zero
> script.py(3)func()
-> return 0 / 0
(Pdb)
In den meisten Situationen reichen der Druckbefehl und die Trace-Ergebnisse zum Debuggen von Skripten aus. Manchmal müssen Sie sich jedoch mit dem Programm vertraut machen, um einen komplexen Fehler zu beheben. In solchen Fällen werden im Code Haltepunkte gesetzt und das Programm überprüft. Sie untersuchen zum Beispiel die Argumente von Funktionen, werten Ausdrücke aus, überprüfen die Werte von Variablen oder führen, wie oben gezeigt, einfach eine schrittweise Codeausführung durch. Pdb ist ein voll funktionsfähiger Python-Wrapper. In dieser Shell können Sie fast alles tun. Im Laufe der Arbeit werden sich einige spezielle Debugger-Befehle als nützlich erweisen, für die Sie
hier Hilfe finden.
Mehrere Konstruktoren in einer Klasse deklarieren
Funktionsüberladung ist eine der Funktionen, die in verschiedenen Programmiersprachen weit verbreitet sind, jedoch nicht in Python. Und obwohl Sie eine reguläre Funktion in Python nicht überladen können, können Sie Konstruktoren mit Klassenmethoden überladen:
import datetime class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day @classmethod def today(cls): t = datetime.datetime.now() return cls(t.year, t.month, t.day) d = Date.today() print(f"{d.day}/{d.month}/{d.year}")
In einer ähnlichen Situation könnten Sie versucht sein, anstelle von Klassenmethoden die gesamte Logik alternativer Konstruktoren in
__init__
und das Problem mit
*args
,
**kwargs
und vielen
if
lösen. Das Ergebnis kann ein funktionierender Code sein, der jedoch schwer zu lesen und zu warten ist. Hier würde ich empfehlen, ein Minimum an Logik in
__init__
und alle Operationen in separaten Methoden / Konstruktoren durchzuführen. Mit diesem Ansatz verfügen wir über einen sauberen Code, der sowohl für den Autor dieses Codes als auch für denjenigen, der diesen Code verwendet, von Vorteil ist.
Caching von Funktionsaufrufergebnissen mit einem Decorator
Haben Sie jemals Funktionen geschrieben, die langwierige Lese- / Schreibvorgänge oder eher langsame rekursive Berechnungen durchgeführt haben? Dachten Sie gleichzeitig, dass das Zwischenspeichern der Ergebnisse solche Funktionen nicht beeinträchtigen würde? Sie können die Ergebnisse eines Funktionsaufrufs mit dem
lru_cache
Dekorator aus dem
functools
Modul zwischenspeichern (
lru_cache
functools
:
from functools import lru_cache import requests @lru_cache(maxsize=32) def get_with_cache(url): try: r = requests.get(url) return r.text except: return "Not Found" for url in ["https://google.com/", "https://martinheinz.dev/", "https://reddit.com/", "https://google.com/", "https://dev.to/martinheinz", "https://google.com/"]: get_with_cache(url) print(get_with_cache.cache_info())
In diesem Beispiel führen wir GET-Anforderungen aus, deren Ergebnisse zwischengespeichert werden (bis zu 32 Ergebnisse können zwischengespeichert werden). Hier können Sie sehen, dass wir mit der
cache_info
Methode Informationen über den Funktionscache
cache_info
. Der Dekorator gibt uns auch die Methode
clear_cache
, mit der
clear_cache
Cache
clear_cache
. An dieser Stelle möchte ich auch darauf hinweisen, dass das Caching nicht mit Funktionen verwendet werden kann, die Nebenwirkungen haben, oder mit Funktionen, die bei jedem Aufruf veränderbare Objekte erstellen.
Suchen nach Elementen, die am häufigsten im iterablen Objekt gefunden werden
In der Liste der Elemente zu stehen, die häufiger vorkommen als andere, ist eine sehr häufige Aufgabe. Sie können es beispielsweise mit der
for
Schleife und einem Wörterbuch lösen, das Informationen über die Anzahl identischer Elemente sammelt. Ein solcher Ansatz ist jedoch Zeitverschwendung. Tatsache ist, dass Sie solche Probleme mit der
Counter
Klasse aus dem
collections
Modul lösen können:
from collections import Counter cheese = ["gouda", "brie", "feta", "cream cheese", "feta", "cheddar", "parmesan", "parmesan", "cheddar", "mozzarella", "cheddar", "gouda", "parmesan", "camembert", "emmental", "camembert", "parmesan"] cheese_count = Counter(cheese) print(cheese_count.most_common(3))
Die internen Mechanismen der
Counter
Klasse basieren auf einem Wörterbuch, in dem die Entsprechung der Elemente und die Anzahl der Einträge in der Liste gespeichert sind. Daher kann das entsprechende Objekt als reguläres
dict
werden:
print(cheese_count["mozzarella"])
Darüber hinaus verfügen wir bei der Arbeit mit
Counter
über die Methode
update(more_words)
, mit der dem Counter neue Elemente hinzugefügt werden. Eine weitere nützliche Funktion von
Counter
ist, dass Sie mathematische Operationen (Addition und Subtraktion) verwenden können, wenn Sie mit Instanzen dieser Klasse arbeiten.
Zusammenfassung
Ich denke, dass die meisten der heute gegebenen Tipps von denen verwendet werden können, die fast täglich in Python schreiben. Ich hoffe, Sie finden unter ihnen etwas, das für Sie nützlich ist.
Sehr geehrte Leser! Kennen Sie interessante Python-Programmiertricks? Wenn ja, teilen Sie sie bitte.
