Code wird öfter gelesen als geschrieben. Deshalb gibt es für Python einen gemeinsamen Stil, den PEP 8 festlegt, und eine Denkweise, die man pythonic nennt: einfach, lesbar, mit den Mitteln der Sprache.
Das Zen of Python
Mit import this zeigt Python seine Leitsätze. Einige davon:
import contextlib, io
text = io.StringIO()
with contextlib.redirect_stdout(text):
import this # druckt das Gedicht beim Import
zeilen = text.getvalue().splitlines()
print(zeilen[2])
print(zeilen[3])
print(zeilen[6])Beautiful is better than ugly. Explicit is better than implicit. Flat is better than nested.
Namen
| Was | Schreibweise | Beispiel |
|---|---|---|
| Variablen, Funktionen, Module | kleinbuchstaben_mit_unterstrich | anzahl_kunden |
| Klassen | GrossBuchstabenAmAnfang | Warenkorb |
| Konstanten | GROSS_MIT_UNTERSTRICH | MAX_VERSUCHE |
| "intern" | führender Unterstrich | _hilfsfunktion |
Aussagekräftige Namen sind wichtiger als kurze: zinssatz statt z.
Formatierung
- 4 Leerzeichen pro Einrückungsebene, keine Tabs
- Zeilen höchstens etwa 79 bis 99 Zeichen lang
- Zwei Leerzeilen zwischen Funktionen und Klassen auf oberster Ebene, eine zwischen Methoden
- Leerzeichen um Operatoren (
a + b), aber nicht in Aufrufen (f(a, b),x[1]) - Imports oben, getrennt nach Standardbibliothek, Fremdpaketen und eigenem Code
Muss man das von Hand prüfen? Nein, dafür gibt es Werkzeuge: ruff und black formatieren und prüfen automatisch (pip install ruff, dann ruff format . und ruff check .).
Pythonic schreiben
Vergleiche links die umständliche und rechts die pythonische Variante:
zahlen = [3, 8, 1, 9]
# umständlich
quadrate = []
for i in range(len(zahlen)):
quadrate.append(zahlen[i] ** 2)
# pythonic
quadrate2 = [z ** 2 for z in zahlen]
print(quadrate == quadrate2)
# Index und Wert zusammen
for i, z in enumerate(zahlen, start=1):
print(i, z)
# parallel durchlaufen
namen = ["Mia", "Tom"]
alter = [17, 19]
for n, a in zip(namen, alter):
print(n, a)True 1 3 2 8 3 1 4 9 Mia 17 Tom 19
Weitere typische Muster:
# Werte tauschen
a, b = 1, 2
a, b = b, a
# Wahrheitswerte direkt nutzen
liste = []
if not liste:
print("leer")
# Standardwert
config = {"port": 8080}
print(config.get("host", "localhost"))
# Strings zusammensetzen
print(", ".join(["a", "b", "c"]))
# any / all statt Schleife
print(any(x > 5 for x in [1, 6]), all(x > 0 for x in [1, 2]))
# Dateien immer mit with
# with open("daten.txt") as f: ...leer localhost a, b, c True True
Dokumentation
Funktionen bekommen einen Docstring, also einen Text in dreifachen Anführungszeichen direkt nach der Kopfzeile:
def flaeche(breite, hoehe):
"""Berechnet die Fläche eines Rechtecks.
Args:
breite: Breite in Metern.
hoehe: Höhe in Metern.
Returns:
Die Fläche in Quadratmetern.
"""
return breite * hoehe
print(flaeche.__doc__.splitlines()[0])
help(flaeche)Berechnet die Fläche eines Rechtecks.
Help on function flaeche in module __main__:
flaeche(breite, hoehe)
Berechnet die Fläche eines Rechtecks.
Args:
breite: Breite in Metern.
hoehe: Höhe in Metern.
Returns:
Die Fläche in Quadratmetern.Häufige Fehler
- Veränderliche Standardwerte wie
def f(liste=[])(nimmNoneund lege die Liste in der Funktion an) - Pauschales
except:ohne Fehlertyp - Mit
==aufNoneprüfen statt mitis None - Dateien ohne
withöffnen - Sehr lange Funktionen statt kleiner, benannter Schritte
Merke
- PEP 8 ist der gemeinsame Stil:
snake_case, 4 Leerzeichen, aussagekräftige Namen - Werkzeuge wie ruff und black formatieren automatisch
- Pythonic: Comprehensions,
enumerate,zip,with,join,any/all - Docstrings dokumentieren Funktionen, Kommentare erklären das Warum
- Keine veränderlichen Standardwerte und kein pauschales
except:
Aufgabe
Nimm ein älteres Programm von dir, lass ruff check darüber laufen und verbessere Namen, Docstrings und Schleifen nach den Mustern dieses Kapitels.