Einführung
Dieses Dokument legt die Konventionen für Python-Code in Pythons
Hauptdistribution fest. Bitte beachte das entsprechende
informative PEP, das die Stilrichtlinien für C-Code in der
Python-C-Implementierung beschreibt[1].
Dieses Dokument entstand aus Guidos ursprünglicher "Python Style
Guide"-Abhandlung[2], mit ein paar Ergänzungen aus Barrys Stil-Leitfaden[5].
Wo es Überschneidungen gab, wurde Guidos Stil für dieses PEP
bevorzugt. Dieses PEP dürfte immer noch lückenhaft sein (in der Tat
wird es wohl nie fertig werden <zwinker>).
Törichte Konsistenz ist des Kleingeistes Kobold
Eine von Guidos wichtigsten Erkenntnissen ist, dass Quelltext weit häufiger
gelesen als geschrieben wird. Die Richtlinien, die hier dargestellt
werden, sollen dazu dienen, die Lesbarkeit von Code zu steigern und ihn
über das weite Spektrum von Python-Code hinweg konsistent zu halten.
Wie schon PEP 20 [6] sagt: "Lesbarkeit zählt".
Ein Stil-Leitfaden hat viel mit Konsistenz zu tun. Konsistenz mit diesem
Stil-Leitfaden ist wichtig. Konsistenz innerhalb eines Projektes ist
wichtiger. Konsistenz innerhalb eines Modules oder einer Funktion ist am
wichtigsten.
Aber am wichtigsten ist, zu wissen, wann man inkonsistent sein kann --
manchmal ist der Stil-Leitfaden schlichtweg nicht anwendbar. Im Zweifelsfall
folge deinem eigenen Ermessen. Schau dir andere Beispiele an und
entscheide, was am besten aussieht. Und zögere nicht zu fragen!
Zwei gute Gründe, eine bestimmte Regel zu brechen, sind:
(1) Würde man die Regel anwenden, so würde der Code weniger lesbar, selbst
für jemanden, der es gewohnt ist Code zu lesen, der die Regeln
befolgt.
(2) Man möchte mit umgebendem Code konform bleiben, der die Regel ebenso
bricht (vielleicht aus historischen Gründen) -- jedoch ist das auch
eine Gelegenheit, mit der Unordnung eines anderen aufzuräumen (in
wahrer "Extreme Programming"-Manier).
Code-Aufbau
Einrückung
Benutze 4 Leerzeichen pro Einrückungsebene.
Für wirklich alten Code, den du nicht in Unordnung bringen willst,
kannst du weiterhin 8-Zeichen-Tabulatoren nehmen.
Tabulatoren oder Leerzeichen?
Vermische nie Tabulatoren und Leerzeichen.
Die gebräuchlichste Art in Python einzurücken ist es, nur Leerzeichen
zu verwenden. Die zweithäufigste Art ist, nur Tabulatoren zu benutzen.
Code, der mit einer Mischung von beidem eingerückt ist, sollte so
umgebaut werden, dass nur noch Leerzeichen benutzt werden. Wird der
Python-Kommandozeileninterpreter mit der '-t'-Option aufgerufen, so
meldet er Warnungen bezüglich Code, der unzulässig Leerzeichen und
Tabulatoren mischt. Benutzt man '-tt', werden aus diesen Warnungen
Fehler. Diese Optionen sind sehr zu empfehlen!
Für neue Projekte werden nur Leerzeichen gegenüber Tabulatoren
empfohlen. Die meisten Editoren haben Funktionen, die das einfach
machen.
Maximale Zeilenlänge
Beschränke alle Zeilen auf eine maximale Länge von 79 Zeichen.
Es gibt immer noch viele Geräte, die auf 80 Zeichen pro Zeile
beschränkt sind; außerdem macht es eine Beschränkung von Fenstern auf 80
Zeichen möglich, mehrere Fenster nebeneinander zu haben. Der
standardmäßige Zeilenumbruch auf diesen Geräten unterbricht die
visuelle Struktur des Codes und macht ihn schwierig zu verstehen.
Darum beschränke bitte alle Zeilen auf ein Maximum von 79 Zeichen. Für
lange, fließende Textblöcke (Docstrings oder Kommentare) ist eine
Beschränkung der Länge auf 72 Zeichen empfohlen.
Die bevorzugte Art, lange Zeilen zu umbrechen, ist Pythons automatische
Zeilenfortsetzung innerhalb von runden, eckigen und geschweiften
Klammern. Sollte es nötig sein, kannst du ein zusätzliches Paar
Klammern um einen Ausdruck verwenden, allerdings sieht manchmal ein
umgekehrter Schrägstrich (Backslash) besser aus. Stelle sicher, dass
die fortgesetzte Zeile richtig eingerückt ist. Die bevorzugte Stelle,
um nahe einem binären Operator zu umbrechen, ist *nach* ihm und nicht
davor.
Ein paar Beispiele:
class Rectangle(Blob):
def __init__(self, width, height,
color='black', emphasis=None, highlight=0):
if width == 0 and height == 0 and \
color == 'red' and emphasis == 'strong' or \
highlight > 100:
raise ValueError("sorry, you lose")
if width == 0 and height == 0 and (color == 'red' or
emphasis is None):
raise ValueError("I don't think so -- values are %s, %s" %
(width, height))
Blob.__init__(self, width, height,
color, emphasis, highlight)
Leerzeilen
Trenne Funktions- und Klassendefinitionen auf höchster Ebene mit zwei
Leerzeilen.
Methodendefinitionen innerhalb einer Klasse werden durch eine einzelne
Leerzeile getrennt.
Zusätzliche Leerzeilen dürfen (sparsam) genutzt werden, um
Funktionsgruppen zu trennen. Zwischen verwandten Bündeln aus
Einzeilern (z.B. eine Gruppe von Dummy-Implementierungen) können sie
ausgelassen werden.
Benutze Leerzeilen, sparsam, um logische Abschnitte zu kennzeichnen.
Python akzeptiert Steuerung-L (d.h. ^L), das Seiten-Vorschub-Zeichen,
als Leerraum. Viele Werkzeuge interpretieren dieses Zeichen als
Seitentrenner, also darfst du es benutzen, um Seiten verwandter
Sektionen deiner Datei voneinander zu trennen.
Kodierungen (PEP 263)
Code im Kern der Python-Distribution sollte immer ASCII- oder Latin-1-
Kodierung (auch bekannt als ISO-8859-1) verwenden. Im Falle von Python
3.0 und seiner Nachfolger wird UTF-8 gegenüber Latin-1 bevorzugt,
siehe PEP 3120.
Dateien, die ASCII (oder im Falle von Python 3.0 UTF-8) verwenden, sollten
keine Zeile mit Angabe der Kodierung (coding cookie) beinhalten. Latin-1 (oder
UTF-8) sollte nur genutzt werden, wenn in einem Kommentar oder Docstring
der Name eines Autors erwähnt wird, welcher Latin-1 erfordert;
ansonsten ist der bevorzugte Weg, um Nicht-ASCII-Daten einzubinden,
die Benutzung von Escape-Sequenzen mit \x, \u oder \U.
Im Falle von Python 3.0 und seiner Nachfolger ist die folgende
Richtlinie für die Standardbibliothek vorgeschrieben (siehe PEP 3131):
Alle Bezeichner der Standardbibliothek MÜSSEN komplett ASCII sein und
SOLLTEN wenn möglich englische Wörter benutzen (in vielen Fällen werden
Abkürzungen und Fachausdrücke benutzt, die nicht englisch sind).
Zusätzlich müssen String-Literale und Kommentare ebenfalls ASCII sein.
Die einzigen Ausnahmen sind: a) Testfälle, welche nicht-ASCII-Fähigkeiten
überprüfen, und b) Namen der Autoren. Autoren, deren Namen nicht auf
dem lateinischen Alphabet basieren, MÜSSEN eine lateinische Übersetzung
ihrer Namen anbieten.
Open-Source-Projekte mit einer weltweiten Zielgruppe sollten sich
ermuntert fühlen, eine ähnliche Regelung anzuwenden.
Importe
- Importe sollten normalerweise auf separaten Zeilen stehen, z.B.:
So: import os
import sys
So nicht: import os, sys
aber folgendes ist in Ordnung:
from subprocess import Popen, PIPE
- Importe stehen immer am Anfang der Datei, gleich nach den Modulkommentaren
und Docstrings, aber noch vor globalen Variablen des Moduls und
Konstanten.
Importe sollten folgendermaßen angeordnet sein:
1. Importe aus der Standardbibliothek
2. Importe von Drittanbieter-Modulen
3. lokale anwendungs-/bibliotheksspezifische Importe
Du solltest eine Leerzeile zwischen jede Importgruppe einfügen.
Stelle relevante __all__-Angaben den Importen hintenan.
- Von relativen Importen innerhalb eines Pakets wird dringendst abgeraten.
Benutze immer den absoluten Paketpfad für alle Importe.
Auch wenn PEP 328[7] nun vollständig in Python 2.5 implementiert ist, wird
von seinem Stil expliziter relativer Importe energisch abgeraten;
absolute Importe sind portabler und meistens lesbarer.
- Wenn man eine Klasse aus einem enthaltenden Modul importiert, so
ist folgende Schreibweise normalerweise in Ordnung:
from myclass import MyClass
from foo.bar.yourclass import YourClass
Falls diese Schreibweise lokale Namenskonflikte hervorruft, dann benenne
sie
import myclass
import foo.bar.yourclass
und benutze "myclass.MyClass" sowie "foo.bar.yourclass.YourClass"
Leerräume in Ausdrücken und Anweisungen
Pet Peeves [Anm. d. Übersetzers: Pet Peeves sind Nichtigkeiten, über die
man sich trotzdem gerne aufregt]
Vermeide belanglose Leerräume in folgenden Situationen:
- Unmittelbar innerhalb von runden, eckigen oder geschweiften
Klammern.
So: spam(ham[1], {eggs: 2})
So nicht: spam( ham[ 1 ], { eggs: 2 } )
- Unmittelbar vor einem Komma, Strichpunkt oder Punkt:
So: if x == 4: print x, y; x, y = y, x
So nicht: if x == 4 : print x , y ; x , y = y , x
- Unmittelbar vor der öffnenden Klammer, die eine Indizierung oder
einen Schnitt einleitet:
So: dict['key'] = list[index]
So nicht: dict ['key'] = list [index]
- Mehr als ein Leerzeichen um einen Zuweisungsoperator
(oder sonstige) herum, um die Einrückung anzugleichen.
So:
x = 1
y = 2
long_variable = 3
So nicht:
x = 1
y = 2
long_variable = 3
Weitere Empfehlungen
- Umgebe folgende binäre Operatoren immer mit einem Leerzeichen auf
jeder Seite: Zuweisung (=), verkürzte Zuweisung (+=, -=, usw.),
Vergleiche (==, <, >, !=, <=, >=, in, not in, is, is not), Bool'sche
Operatoren (and, or, not).
- Benutze Leerzeichen um arithmetische Operatoren herum:
So:
i = i + 1
submitted += 1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
So nicht:
i=i+1
submitted +=1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
- Benutze keine Leerzeichen um das '='-Zeichen herum, wenn es benutzt
wird, um ein Schlüsselwort-Argument oder einen Standardparameter-Wert
anzuzeigen.
So:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
So nicht:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)
- Von zusammengefassten Anweisungen (mehrere Anweisungen auf derselben Zeile)
wird generell abgeraten.
So:
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
do_three()
Lieber nicht:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
- Während es manchmal in Ordnung ist, ein kurzes if/for/while auf
die gleiche Zeile zu setzen, gilt dies niemals für Anweisungen
mit mehreren Abschnitten. Vermeide außerdem, solch lange Zeilen zu
umbrechen!
Lieber nicht:
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()
Definitiv nicht:
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
list, like, this)
if foo == 'blah': one(); two(); three()
Kommentare
Kommentare, die dem Code widersprechen, sind schlimmer als keine
Kommentare. Es ist wichtig, dass die Kommentare aktuell bleiben, auch wenn
der Code sich ändert!
Kommentare sollten aus kompletten Sätzen bestehen. Wenn ein Kommentar eine
Phrase oder ein Satz ist, so sollte das erste Wort groß geschrieben werden,
sofern es kein Bezeichner ist, der mit einem kleinen Buchstaben beginnt
(verändere nie die Schreibung eines Bezeichners!).
Ist ein Kommentar kurz, so kann der Punkt am Ende ausgelassen werden.
Blockkommentare bestehen generell aus einem oder mehreren Paragraphen, die
aus kompletten Sätzen aufgebaut sind, wobei jeder Satz in einem Punkt
enden sollte.
Du solltest 2 Leerzeichen nach einem satzbeendenden Punkt verwenden.
Schreibt man in Englisch, so ist Strunk & White anzuwenden. [Anm d.
Übersetzers: http://en.wikisource.org/wiki/The_Elements_of_Style]
An Python-Programmierer aus nicht englisch sprechenden Ländern: Bitte
schreibt eure Kommentare auf Englisch, es sei denn ihr seid 120% sicher,
dass der Code nie von Leuten gelesen wird, die eure Sprache nicht
sprechen.
Blockkommentare
Blockkommentare treffen generell auf einigen (oder allen) folgenden
Code zu und sind auf der selben Einrückungsebene wie der Code. Jede
Zeile des Blockkommentares beginnt mit einem # und einem einzelnen
Leerzeichen (sofern es kein eingerückter Text im Kommentar ist).
Absätze innerhalb eines Blockkommentars werden durch eine Zeile,
die nur ein einzelnes # enthält, gekennzeichnet.
In-line-Kommentare
Benutze in-line-Kommentare sparsam.
Ein in-line-Kommentar ist ein Kommentar auf der selben Zeile wie eine
Anweisung. In-line-Kommentare sollten durch zwei Leerzeichen von der
Anweisung getrennt werden. Sie sollten mit einem # und einem
Leerzeichen beginnen.
In-line-Kommentare sind unnötig und tatsächlich störend, wenn
sie nur das Offensichtliche feststellen. Schreibe niemals folgendes:
x = x + 1 # Increment x
Aber manchmal ist dies nützlich:
x = x + 1 # Compensate for border
Dokumentation im Code
Konventionen, die das Schreiben guter Dokumentations-Blöcke (auch bekannt als
'Docstrings') betreffen, sind in PEP 257 [3] verewigt.
- Schreibe Docstrings für alle öffentlichen Module, Funktionen, Klassen
und Methoden. Docstrings sind bei nicht-öffentlichen Methoden unnötig,
aber sie sollten einen Kommentar haben, der beschreibt, was die
Methode macht. Dieser Kommentar sollte nach der 'def' Zeile stehen.
- PEP 257 beschreibt gute Docstring-Konventionen. Beachte, dass es sehr
wichtig ist, dass die """, die einen mehrzeiligen Docstring beenden,
sich auf einer eigenen Zeile befinden und vorzugsweise noch eine
Leerzeile vor sich haben, zum Beispiel:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
- Für einzeilige Docstrings ist es in Ordnung, die schließenden """ auf
der selben Zeile zu schreiben.
Versionsbuchhaltung
Wenn du unbedingt Subversion-, CVS- oder RCS-Kram in deiner Quelltext-Datei
haben musst, dann verwende folgendes:
__version__ = "$Revision: 63990 $"
# $Source$
Diese Zeilen sollten nach dem Docstring des Moduls eingefügt werden, vor
jeglicher anderer Zeile Code, mit einer vorangehenden und einer folgenden Leerzeile.
Bennenungskonventionen
Die Bennenungskonventionen von Pythons Bibliothek sind eine einzige
Unordnung, darum werden wir das wohl nie komplett konsistent hinbekommen --
trotzdem gibt es hier die derzeit empfohlenen Benennungsstandards. Neue
Module und Pakete (einschließlich Frameworks von Dritten) sollten gemäß
diesen Standards geschrieben werden. Gibt es jedoch eine existierende
Bibliothek mit einem anderen Stil, so ist deren interne Konsistenz vorzuziehen.
Zur Veranschaulichung: Benennungsstil
Es gibt jede Menge von unterschiedlichen Benennungsstilen. Es ist
hilfreich zu erkennen, welche benutzt werden, unabhängig davon wofür
sie genutzt werden.
Gewöhnlich unterscheidet man unter folgenden:
- b (einzelner Kleinbuchstabe)
- B (einzelner Großbuchstabe)
- lowercase (klein geschrieben)
- lower_case_with_underscores (klein geschrieben mit Unterstrichen)
- UPPERCASE (groß geschrieben)
- UPPER_CASE_WITH_UNDERSCORES (groß geschrieben mit Unterstrichen)
- CapitalizedWords (oder CapWords, oder CamelCase -- nach dem
holprigen Aussehen seiner Buchstaben benannt[4]. Auch als StudlyCaps
bekannt.
Beachte: Benutzt man Abkürzungen in CapWords, dann sollte man alle
Buchstaben der Abkürzung groß schreiben. So ist HTTPServerError
gegenüber HttpServerError zu bevorzugen.
- mixedCase (Unterscheidet sich von CapWords durch den klein
geschriebenen Anfangsbuchstaben!)
- Capitalized_Words_With_Underscores (hässlich!)
Außerdem gibt es noch den Stil, eindeutige Präfixe bei einer Gruppe
verwandter Namen zu benutzen. In Python ist das nicht üblich, soll aber
hier der Vollständigkeit halber erwähnt werden. Beispielsweise gibt die
os.stat()-Funktion ein Tupel zurück, dessen Elemente traditionell
Namen wie st_mode, st_size, st_mtime usw. haben (diese wurden gewählt, um
die Übereinstimmung mit den Feldern des entsprechenden POSIX-Systemaufrufs
zu betonen, und hilft so Programmierern, die damit vertraut sind).
Die X11-Bibliothek benutzt ein führendes X für alle seine öffentlichen
Funktionen. In Python wird dieser Stil generell als unnötig erachtet,
da Attributs- und Methodennamen ein vorangestelltes Objekt haben.
Funktionen haben entsprechend einen vorangestellten Modulnamen.
Zusätzlich sind folgende spezielle Formen, die führende oder
angehängte Unterstriche benutzen, anerkannt (diese können generell mit
allen Groß-/Kleinschreibungskonventionen kombiniert werden):
- _einzelner_führender_unterstrich: Schwacher Hinweis auf 'nur für die
interne Nutzung'. So importiert ein 'from M import *' beispielsweise keine
Objekte, deren Namen mit einem Unterstrich beginnen.
- einzelner_angehängter_unterstrich_: Wird gemäß Konvention verwendet, um
Konflikte mit Python Schlüsselwörtern zu vermeiden, z.B.:
Tkinter.Toplevel(master, class_='ClassName')
- __doppelte_führende_und_angehängte_unterstriche__: 'magische'
Objekte oder Attribute, die in vom Benutzer kontrollierten
Namensräumen existieren. Beispielsweise __init__, __import__ oder
__file__. Erfinde niemals solche Namen; benutze sie nur so wie es
dokumentiert ist.
Vorgeschriebenes: Bennenungskonventionen
Vermeidenswerte Namen
Benutze niemals die Zeichen `l' (kleines L), `O' (großes o) oder
`I' (großes i) als Variablename mit nur einem Zeichen.
In einigen Schriftarten sind diese ununterscheidbar von den
Ziffern null und eins. Wenn du versucht bist, `l' zu verwenden,
benutze stattdessen `L'.
Paket- und Modulnamen
Module sollten kurze, komplett klein geschriebene Namen haben.
Unterstriche können im Modulnamen benutzt werden, sofern es die
Lesbarkeit unterstützt. Python-Pakete sollten ebenfalls kurze,
komplett klein geschriebene Namen haben, allerdings wird hier von
der Benutzung von Unterstrichen abgeraten.
Da Modulnamen auf Dateinamen abgebildet werden, und einige
Dateisysteme Groß-/Kleinschreibung nicht unterscheiden, sowie lange
Namen abschneiden, ist es wichtig, dass ziemlich kurze Modulnamen
ausgesucht werden -- dies ist kein Problem unter Unix, aber es
könnte eines sein, wenn der Code auf ältere Mac- und
Windowsversionen oder DOS transportiert wird.
Wenn ein Erweiterungsmodul, das in C oder C++ geschrieben ist, ein
begleitendes Python-Modul hat, das ein Interface auf höherer
Ebene (z.B. mit ausgeprägterer Objektorientierung) bereitstellt,
so hat das C/C++ Modul einen führenden Unterstrich (z.B. _socket).
Klassennamen
Fast ohne Ausnahme sollten Klassennamen der CapWord Konvention
folgen. Klassen für interne Benutzung haben einen führenden
Unterstrich.
Ausnahmennamen
Da Ausnahmen Klassen sein sollten, trifft hier die
Klassen-Konvention zu. Jedoch solltest du ein 'Error' an die
Ausnahmennamen anhängen (sofern die Ausnahme wirklich ein Fehler
ist).
Globale Variablennamen
(Hoffentlich sind diese Variablen nur für die Benutzung innerhalb
eines Moduls gedacht.) Die Konventionen sind hier die gleichen wie
für Funktionen.
Module, die für die Benutzung per 'from M import *' konzipiert
sind, sollten den __all__-Mechanismus benutzen um den Export der
globalen Variablen zu verhindern oder der älteren Konvention des
Voranstellens von Unterstrichen bei globalen Variablen folgen (was
du eventuell möchtest, um zu verdeutlichen, dass diese globale
Variablen nicht öffentlich außerhalb des Moduls sind)
Funktionsnamen
Funktionsnamen sollten klein geschrieben und Unterstriche
als Worttrenner verwendet werden, sofern das die Lesbarkeit
steigert.
mixedCase ist nur in Kontexten erlaubt, wo dies schon der
vorherrschende Stil (z.B. threading.py) ist, um
Rückwärtskompatibilität zu gewährleisten.
Funktions- und Methodenargumente
Benutze immer 'self' als das erste Argument einer Instanzmethode.
Benutze immer 'cls' als das erste Argument einer Klassenmethode.
Sollte der Name eines Funktionsargumentes sich mit einem
reservierten Schlüsselwort überschneiden, so ist es generell
besser, einen einzigen Unterstrich anzuhängen, statt das Wort
abzukürzen oder falsch zu schreiben. So ist 'print_' besser als
'prnt'. (Vielleicht ist es auch besser, solche Kollisionen zu
vermeiden, indem man Synonyme benutzt).
Methodennamen und Instanzvariablen
Benutze die Benennungsregeln für Funktionen: Kleinschreibung mit
Unterstrichen als Worttrennern, sofern es der Lesbarkeit dient.
Benutze einen führenden Unterstrich nur für nicht-öffentliche
Methoden und Instanzvariablen.
Um Namenskonflikte mit Unterklassen zu vermeiden, benutze zwei
führende Unterstriche, so dass Pythons Namensvermengungs-Regeln
angewendet werden.
Python vermengt diese Namen mit dem Klassennamen: Hat die Klasse
Foo ein Attribut, das __a benannt ist, so kann es nicht über
Foo.__a angesprochen werden. (Ein hartnäckiger Benutzer könnte
immer noch Zugang bekommen, in dem er Foo._Foo__a aufruft.)
Generell sollten doppelte, führende Unterstriche nur genutzt
werden, um Namenskonflikte mit Attributen in Klassen, die darauf
angelegt wurden geerbt zu werden, vorzubeugen.
Beachte: Es gibt ein wenig Streit über die Benutzung von __-Namen
(siehe unten).
Gestaltung zur Vererbung
Entscheide dich immer, ob die Methoden und Instanzvariablen
(insgesamt: 'Attribute') einer Klasse öffentlich oder
nicht-öffentlich sein sollten. Im Zweifelsfall sollten sie
nicht-öffentlich sein; es ist einfacher, sie später öffentlich zu
machen als umgekehrt.
Öffentliche Attribute sind die, von denen du erwartest, dass sie
auch von nicht mit deiner Klasse in direkter Verbindung stehendem
Code benutzt werden; sie erfordern deine Bereitschaft, Veränderungen
zu vermeiden, die eine Rückwärtsinkompatibilität bewirken würden.
Nicht-öffentliche Attribute sind solche, die nicht dazu gedacht
sind von Dritten benutzt zu werden; du garantierst nicht, dass
sich nicht-öffentliche Attribute nicht verändern oder sogar
entfernt werden.
Wir benutzen hier nicht den Terminus 'private', da es keine
Attribute in Python gibt die wirklich privat sind (ohne einen generell
unnötigen Arbeitsaufwand).
Eine andere Kategorie von Attributen ist die, die Teil der
'subclass API' sind (in anderen Sprachen oft 'protected' genannt).
Manche Klassen sind dazu ausgelegt, 'geerbt' zu werden, entweder um
Aspekte des Klassenverhaltens zu erweitern oder zu ändern. Wenn
man so eine Klasse entwirft, dann sollte man sich darum kümmern,
dass man klare Entscheidungen trifft, welche Attribute öffentlich
sind, welche Teil der 'subclass API' sind und welche wirklich nur
dazu gedacht sind, von der Basisklasse benutzt zu werden.
Zu diesem Zweck gibt es ein paar 'Pythonic' Richtlinien:
- Öffentliche Attribute haben keinen führenden Unterstrich.
- Falls dein öffentlicher Attributsname sich mit einem
reservierten Schlüsselwort überschneidet, dann hänge einen
einzigen Unterstrich an. Dies ist dem Abkürzen oder falsch
Schreiben vorzuziehen. (Trotz dieser Regel ist 'cls' die bevorzugte
Schreibweise für jede Variable bzw. jedes Argument, von dem bekannt
ist, dass sie/es eine Klasse ist. Das gilt vor allem für
Klassenmethoden.)
Beachte: Namensempfehlungen für Argumente bei Klassenmethoden,
siehe oben.
- Für einfache öffentliche Datenattribute ist es am besten, nur
die Attributsnamen zu zeigen, ohne komplizierte
Zugriffs-/Veränderungsmethoden. Behalte im Sinn, dass Python
einen einfachen Weg für zukünftige Erweiterungen bereitstellt,
solltest du entscheiden, dass ein einfaches Datenattribut
funktionelles Verhalten entwickeln sollte. In diesem Fall
sollte man Eigenschaften verwenden, um die funktionelle
Implementierung hinter einer einfachen Datenattributs-
Zugriffssyntax zu verstecken.
Beachte 1: Eigenschaften funktionieren nur mit new-style
Klassen.
Beachte 2: Versuche funktionelles Verhalten frei von
Nebeneffekten zu halten, jedoch sind Nebeneffekte wie Caching
generell in Ordnung.
Beachte 3: Vermeide die Benutzung von Eigenschaften für
rechenintensive Operationen; die Attributsnotation lässt den
Aufrufenden in dem Glauben, dass der Zugriff (relativ) günstig
ist.
Programmierempfehlungen
- Code sollte in einer Art geschrieben sein, dass er keine andere
Implementierung von Python (PyPy, Jython, IronPython, Pyrex, Psyco usw.)
benachteiligt.
Zum Beispiel sollte man sich nicht auf CPythons effiziente
Implementierung von In-Place-String-Verkettung für Anweisungen in der
Form von a+=b oder a=a+b verlassen. Diese Anweisungen laufen langsamer
in Jython. In leistungsempfindlichen Teilen der Bibliothek sollte
stattdessen die ''.join()-Form verwendet werden. Das stellt sicher, dass
Verkettung in einer linearen Zeitspanne über verschiedene Implementierungen
hinweg geschieht.
- Vergleiche mit Singletons wie None sollten immer mit 'is' oder 'is not'
bewerkstelligt werden, nie mit den Gleichheitsoperatoren.
Hüte dich außerdem davor 'if x' zu schreiben, wenn du wirklich 'if x is
not None' meinst -- z.B. wenn du überprüfst, ob eine Variable oder ein
Argument, das standardmäßig None ist, seinen Wert änderte. Der andere
Wert könnte von einem Typ sein (wie z.B. ein Container), der in Bool'schem
Kontext 'unwahr' ist (Anm.: z.B. eine leere Liste)!
- Benutze klassenbasierte Ausnahmen
String-Ausnahmen in neuem Code sind verboten, da diese Einrichtung in
Python 2.6 entfernt wird.
Module oder Pakete sollten ihre eigene bereichsspezifische
Grundausnahmeklasse definieren, die von der eingebauten
'Exception'-Klasse erben sollte. Füge immer einen Docstring bei. Z.B.:
class MessageError(Exception):
"""Base class for errors in the email package."""
Namenskonventionen für Klassen sind hier anzuwenden, jedoch solltest du
den Suffix 'Error' an deine Ausnahmeklasse anhängen, wenn die Ausnahme
ein Fehler ist. Nicht-Fehler Ausnahmen benötigen keinen speziellen
Suffix.
- Wenn du eine Ausnahme erhebst, dann benutze 'raise
ValueError("message")' statt der alten Form 'raise ValueError,
"message"'.
Die eingeklammerte Form ist zu bevorzugen, da man aufgrund der Klammern keine
Zeilenfortsetzungszeichen benötigt, wenn die Ausnahmeargumente lang sind
oder Stringformatierungen enthalten. Die ältere Form wird in Python 3.0
entfernt.
- Wenn du Ausnahmen abfängst, erwähne spezifische Ausnahmen, sofern
möglich, statt einer nackten 'except:'-Klausel.
Beispielsweise benutze:
try:
import platform_specific_module
except ImportError:
platform_specific_module = None
Eine nackte 'except:'-Klausel wird auch 'SystemExit'- und
'KeyboardInterrupt'-Ausnahmen abfangen und macht es so schwerer ein
Programm mit Steuerung-C zu unterbrechen, und kann außerdem andere
Probleme maskieren. Wenn du alle Ausnahmen abfangen möchtest, die einen
Programmfehler signalisieren, so benutze 'except Exception:'.
Eine gute Faustregel ist es, die Benutzung von nackten 'except'-Klauseln
auf zwei Fälle zu beschränken:
1) Wenn die Ausnahmebehandlung den Traceback ausgibt oder loggt; so
weiß der Benutzer zumindest, dass ein Fehler auftrat.
2) Wenn der Code Aufräumarbeiten machen muss, aber dann die Ausnahme
sich weiter nach oben verbreiten lässt über ein erneutes 'raise'.
'try...finally' ist allerdings ein besserer Weg das zu handhaben.
- Beschränke die 'try'-Suite, bei allen 'try/except'-Klauseln, außerdem
auf den minimal nötigen Code. Das trägt wieder dazu bei Maskierung von
Fehlern zu vermeiden.
So:
try:
value = collection[key]
except KeyError:
return key_not_found(key)
else:
return handle_value(value)
So nicht:
try:
# Too broad!
return handle_value(collection[key])
except KeyError:
# Will also catch KeyError raised by handle_value()
return key_not_found(key)
- Benutze String-Methoden statt dem Stringmodul.
String-Methoden sind immer viel schneller und teilen das API von
Unicode-Strings. Ignoriere diese Regel, wenn Rückwärtskompatibilität mit
Python-Versionen, die älter als 2.0 sind, wichtig ist.
- Benutze ''.startswith() und ''.endswith() statt String-Ausschnitten um
Prä- oder Suffixe zu überprüfen.
startswith() und endswith() sind sauberer und weniger fehleranfällig.
Zum Beispiel:
So: if foo.startswith('bar'):
So nicht: if foo[:3] == 'bar':
Die Ausnahme ist, wenn dein Code mit Python 1.5.2 funktionieren muss
(aber das hoffen wir mal nicht!).
- Objekt-Typ-Vergleiche sollten immer isinstance() benutzen statt einem
direkten Typ-Vergleich.
So: if isinstance(obj, int):
So nicht: if type(obj) is type(1):
Bei der Überprüfung, ob ein Objekt ein String ist, sollte man im Sinn
behalten, dass es auch ein Unicode-String sein könnte! Seit Python 2.3
haben str und unicode eine gemeinsame Basisklasse, basestring, also
kannst du folgendes verwenden:
if isinstance(obj, basestring):
In Python 2.2 enthält das types-Modul den Typ StringTypes, der für
diesen Zweck definiert wurde.
Zum Beispiel:
from types import StringTypes
if isinstance(obj, StringTypes):
In Python 2.0 und 2.1 sollte man folgendes tun:
from types import StringType, UnicodeType
if isinstance(obj, StringType) or \
isinstance(obj, UnicodeType) :
- Bei Sequenzen (Strings, Listen, Tupel) benutze die Tatsache, dass leere
Sequenzen 'False' sind.
So: if not seq:
if seq:
So nicht: if len(seq)
if not len(seq)
- Schreibe keine String-Literale, die auf erhebliche angehängte Leerräume
vertrauen. Solche angehängten Leerräume sind visuell nicht
unterscheidbar und manche Editoren (oder viel wichtiger, reindent.py)
werden sie kürzen.
- Vergleiche Bool'sche Werte nicht mit True oder False per ==
So: if greeting:
So nicht: if greeting == True:
Schlimmer: if greeting is True:
Referenzen
[1] PEP 7, Style Guide for C Code, van Rossum
[2] http://www.python.org/doc/essays/styleguide.html
[3] PEP 257, Docstring Conventions, Goodger, van Rossum
[4] http://www.wikipedia.com/wiki/CamelCase
[5] Barry's GNU Mailman style guide
http://barry.warsaw.us/software/STYLEGUIDE.txt
[6] PEP 20, The Zen of Python
[7] PEP 328, Imports: Multi-Line and Absolute/Relative