PEP 8 – Style Guide for Python Code
- Autor:
- Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>, Alyssa Coghlan <ncoghlan at gmail.com>
- Status:
- Aktiv
- Typ:
- Prozess
- Erstellt:
- 05-Jul-2001
- Post-History:
- 05-Jul-2001, 01-Aug-2013
Inhaltsverzeichnis
- Einleitung
- Eine törichte Konsistenz ist der Kobold kleiner Geister
- Code-Layout
- String-Anführungszeichen
- Leerzeichen in Ausdrücken und Anweisungen
- Wann Nachgestellte Kommas zu verwenden sind
- Kommentare
- Namenskonventionen
- Programmierempfehlungen
- Referenzen
- Urheberrecht
Einleitung
Dieses Dokument gibt Kodierungsrichtlinien für Python-Code, der die Standardbibliothek in der Haupt-Python-Distribution umfasst. Bitte beachten Sie die begleitende Information PEP, die Styleguides für den C-Code in der C-Implementierung von Python beschreibt.
Dieses Dokument und PEP 257 (Docstring-Konventionen) wurden aus Guidos ursprünglichem Essay zum Python Style Guide übernommen, mit einigen Ergänzungen aus Barrys Styleguide [2].
Dieser Styleguide entwickelt sich im Laufe der Zeit weiter, wenn zusätzliche Konventionen identifiziert und frühere Konventionen durch Änderungen an der Sprache selbst obsolet werden.
Viele Projekte haben ihre eigenen Styleguides. Im Falle von Konflikten haben projektspezifische Leitfäden für dieses Projekt Vorrang.
Eine törichte Konsistenz ist der Kobold kleiner Geister
Eine der wichtigsten Erkenntnisse von Guido ist, dass Code viel öfter gelesen als geschrieben wird. Die hier bereitgestellten Richtlinien sollen die Lesbarkeit von Code verbessern und ihn über das breite Spektrum von Python-Code hinweg konsistent machen. Wie PEP 20 besagt: „Lesbarkeit zählt“.
Ein Styleguide handelt von Konsistenz. Konsistenz mit diesem Styleguide ist wichtig. Konsistenz innerhalb eines Projekts ist wichtiger. Konsistenz innerhalb eines Moduls oder einer Funktion ist am wichtigsten.
Wissen Sie jedoch, wann Sie inkonsistent sein müssen – manchmal sind Styleguide-Empfehlungen einfach nicht anwendbar. Im Zweifel nutzen Sie Ihr bestes Urteilsvermögen. Schauen Sie sich andere Beispiele an und entscheiden Sie, was am besten aussieht. Und zögern Sie nicht zu fragen!
Insbesondere: brechen Sie die Abwärtskompatibilität nicht nur, um diese PEP einzuhalten!
Einige andere gute Gründe, eine bestimmte Richtlinie zu ignorieren
- Wenn die Anwendung der Richtlinie den Code weniger lesbar machen würde, selbst für jemanden, der an das Lesen von Code gewöhnt ist, der dieser PEP folgt.
- Um mit umgebendem Code konsistent zu sein, der ihn ebenfalls bricht (vielleicht aus historischen Gründen) – obwohl dies auch eine Gelegenheit ist, den Müll eines anderen zu beseitigen (im wahren XP-Stil).
- Da der betreffende Code vor der Einführung der Richtlinie existiert und es keinen anderen Grund gibt, diesen Code zu ändern.
- Wenn der Code mit älteren Python-Versionen kompatibel bleiben muss, die die vom Styleguide empfohlene Funktion nicht unterstützen.
Code-Layout
Einrückung
Verwenden Sie 4 Leerzeichen pro Einrückungsebene.
Fortsetzungszeilen sollten entweder vertikal ausgerichtet sein, indem die implizite Zeilenfortsetzung von Python innerhalb von Klammern, eckigen Klammern und geschweiften Klammern verwendet wird, oder durch eine *hängende Einrückung* [1]. Bei der Verwendung einer hängenden Einrückung sollten folgende Punkte beachtet werden: Es sollten keine Argumente in der ersten Zeile stehen und eine weitere Einrückung sollte verwendet werden, um sie klar als Fortsetzungszeile zu kennzeichnen.
# Correct:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
# Wrong:
# Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Further indentation required as indentation is not distinguishable.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
Die 4-Leerzeichen-Regel ist für Fortsetzungszeilen optional.
Optional
# Hanging indents *may* be indented to other than 4 spaces.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
Wenn der bedingte Teil einer if-Anweisung lang genug ist, um über mehrere Zeilen geschrieben werden zu müssen, ist es erwähnenswert, dass die Kombination aus einem zweistelligen Schlüsselwort (d. h. if), plus einem Leerzeichen, plus einer öffnenden Klammer eine natürliche 4-Leerzeichen-Einrückung für die nachfolgenden Zeilen der mehrzeiligen Bedingung erzeugt. Dies kann zu einem visuellen Konflikt mit der eingerückten Code-Suite führen, die in die if-Anweisung verschachtelt ist, die ebenfalls natürlich auf 4 Leerzeichen eingerückt wäre. Dieses PEP nimmt keine explizite Stellung dazu, wie (oder ob) solche bedingten Zeilen visuell von der verschachtelten Suite innerhalb der if-Anweisung unterschieden werden sollen. Akzeptable Optionen in dieser Situation sind unter anderem:
# No extra indentation.
if (this_is_one_thing and
that_is_another_thing):
do_something()
# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
that_is_another_thing):
# Since both conditions are true, we can frobnicate.
do_something()
# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
and that_is_another_thing):
do_something()
(Siehe auch die Diskussion, ob vor oder nach binären Operatoren umgebrochen werden soll.)
Die schließende geschweifte Klammer/eckige Klammer/runde Klammer bei mehrzeiligen Konstrukten kann entweder unter dem ersten Nicht-Leerzeichen-Zeichen der letzten Zeile der Liste ausgerichtet werden, wie in
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
oder sie kann unter dem ersten Zeichen der Zeile ausgerichtet werden, die den mehrzeiligen Konstrukt beginnt, wie in
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
Tabs oder Leerzeichen?
Leerzeichen sind die bevorzugte Einrückungsmethode.
Tabs sollten ausschließlich verwendet werden, um mit bereits mit Tabs eingerücktem Code konsistent zu bleiben.
Python verbietet das Mischen von Tabs und Leerzeichen für die Einrückung.
Maximale Zeilenlänge
Beschränken Sie alle Zeilen auf maximal 79 Zeichen.
Für fließende lange Textblöcke mit weniger strukturellen Einschränkungen (Docstrings oder Kommentare) sollte die Zeilenlänge auf 72 Zeichen beschränkt werden.
Die Begrenzung der erforderlichen Editorfensterbreite ermöglicht es, mehrere Dateien nebeneinander zu öffnen, und funktioniert gut bei der Verwendung von Code-Review-Tools, die die beiden Versionen in benachbarten Spalten darstellen.
Die Standard-Zeilenumbrüche in den meisten Tools stören die visuelle Struktur des Codes und erschweren dessen Verständnis. Die Limits sind so gewählt, dass sie bei einer Fensterbreite von 80 keine Umbrüche verursachen, selbst wenn das Tool beim Umbrechen von Zeilen ein Markierungszeichen in der letzten Spalte platziert. Einige webbasierte Tools bieten möglicherweise überhaupt keine dynamischen Zeilenumbrüche.
Einige Teams bevorzugen eine längere Zeilenlänge. Für Code, der ausschließlich oder hauptsächlich von einem Team gepflegt wird, das sich bei diesem Thema einigen kann, ist es in Ordnung, die Zeilenlängenbegrenzung auf bis zu 99 Zeichen zu erhöhen, vorausgesetzt, Kommentare und Docstrings werden weiterhin bei 72 Zeichen umbrochen.
Die Python-Standardbibliothek ist konservativ und verlangt die Begrenzung von Zeilen auf 79 Zeichen (und Docstrings/Kommentare auf 72).
Die bevorzugte Methode zum Umbrechen langer Zeilen ist die Verwendung der impliziten Zeilenfortsetzung von Python innerhalb von Klammern, eckigen Klammern und geschweiften Klammern. Lange Zeilen können über mehrere Zeilen umbrochen werden, indem Ausdrücke in Klammern gesetzt werden. Diese sollten der Verwendung eines Backslashs zur Zeilenfortsetzung vorgezogen werden.
Backslashes können immer noch angebracht sein. Beispielsweise konnten lange, mehrfache with-Anweisungen vor Python 3.10 keine implizite Fortsetzung verwenden, daher waren Backslashes für diesen Fall akzeptabel.
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
(Siehe die vorherige Diskussion über mehrzeilige if-Anweisungen für weitere Gedanken zur Einrückung solcher mehrzeiliger with-Anweisungen.)
Ein weiterer solcher Fall sind assert-Anweisungen.
Stellen Sie sicher, dass die fortgesetzte Zeile entsprechend eingerückt ist.
Soll eine Zeile vor oder nach einem binären Operator umgebrochen werden?
Jahrzehntelang war der empfohlene Stil, nach binären Operatoren umzubrechen. Dies kann jedoch die Lesbarkeit auf zwei Arten beeinträchtigen: Die Operatoren werden tendenziell über verschiedene Spalten auf dem Bildschirm verstreut und jeder Operator wird von seinem Operanden weg und auf die vorhergehende Zeile verschoben. Hier muss das Auge zusätzliche Arbeit leisten, um zu erkennen, welche Elemente addiert und welche subtrahiert werden.
# Wrong:
# operators sit far away from their operands
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
Um dieses Lesbarkeitsproblem zu lösen, folgen Mathematiker und ihre Verleger der entgegengesetzten Konvention. Donald Knuth erklärt die traditionelle Regel in seiner Serie Computers and Typesetting: „Während Formeln innerhalb eines Absatzes immer nach binären Operationen und Relationen umgebrochen werden, werden angezeigte Formeln immer vor binären Operationen umgebrochen“ [3].
Das Folgen der Tradition aus der Mathematik führt normalerweise zu lesbarerem Code.
# Correct:
# easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
In Python-Code ist es zulässig, vor oder nach einem binären Operator umzubrechen, solange die Konvention lokal konsistent ist. Für neuen Code wird Knuths Stil vorgeschlagen.
Leerzeilen
Umschließen Sie Funktions- und Klassendefinitionen auf Top-Level-Ebene mit zwei Leerzeilen.
Methodendefinitionen innerhalb einer Klasse werden von einer einzelnen Leerzeile umgeben.
Zusätzliche Leerzeilen können (sparsam) verwendet werden, um Gruppen verwandter Funktionen zu trennen. Leerzeilen können zwischen einer Reihe verwandter Einzeiler (z. B. einer Reihe von Dummy-Implementierungen) weggelassen werden.
Verwenden Sie Leerzeilen in Funktionen, sparsam, um logische Abschnitte zu kennzeichnen.
Python akzeptiert das Control-L (d. h. ^L) Form-Feed-Zeichen als Whitespace; viele Tools behandeln diese Zeichen als Seitenunterbrecher, sodass Sie sie verwenden können, um Seiten zusammengehöriger Abschnitte Ihrer Datei zu trennen. Beachten Sie, dass einige Editoren und webbasierte Code-Viewer Control-L möglicherweise nicht als Form-Feed erkennen und stattdessen ein anderes Glyphen anzeigen.
Quellcodedatei-Kodierung
Code in der Kern-Python-Distribution sollte immer UTF-8 verwenden und keine Kodierungsdeklaration haben.
In der Standardbibliothek sollten Nicht-UTF-8-Kodierungen nur zu Testzwecken verwendet werden. Verwenden Sie Nicht-ASCII-Zeichen sparsam, vorzugsweise nur zur Bezeichnung von Orten und menschlichen Namen. Wenn Sie Nicht-ASCII-Zeichen als Daten verwenden, vermeiden Sie laute Unicode-Zeichen wie z̯̯͡a̧͎̺l̡͓̫g̹̲o̡̼̘ und Byte Order Marks.
Alle Bezeichner in der Python-Standardbibliothek MÜSSEN ASCII-kompatible Bezeichner verwenden und SOLLTEN nach Möglichkeit englische Wörter verwenden (in vielen Fällen werden Abkürzungen und Fachbegriffe verwendet, die nicht englisch sind).
Open-Source-Projekte mit globaler Reichweite werden ermutigt, eine ähnliche Politik zu verfolgen.
Imports
- Imports sollten normalerweise in separaten Zeilen erfolgen.
# Correct: import os import sys
# Wrong: import sys, os
Es ist in Ordnung, dies zu tun.
# Correct: from subprocess import Popen, PIPE
- Imports werden immer am Anfang der Datei platziert, direkt nach allen Modulkommentaren und Docstrings und vor Modul-Globale und Konstanten.
Imports sollten in folgender Reihenfolge gruppiert werden:
- Imports der Standardbibliothek.
- Zugehörige Drittanbieter-Imports.
- Lokale Anwendungs-/bibliothekspezifische Imports.
Sie sollten eine Leerzeile zwischen jeder Gruppe von Imports einfügen.
- Absolute Imports werden empfohlen, da sie in der Regel lesbarer sind und sich tendenziell besser verhalten (oder zumindest bessere Fehlermeldungen liefern), wenn das Importsystem falsch konfiguriert ist (z. B. wenn ein Verzeichnis innerhalb eines Pakets auf
sys.pathlandet).import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
Explizite relative Imports sind jedoch eine akzeptable Alternative zu absoluten Imports, insbesondere bei komplexen Paketlayouts, bei denen die Verwendung absoluter Imports unnötig ausführlich wäre.
from . import sibling from .sibling import example
Code der Standardbibliothek sollte komplexe Paketlayouts vermeiden und immer absolute Imports verwenden.
- Beim Importieren einer Klasse aus einem Modul, das Klassen enthält, ist es normalerweise in Ordnung, dies so zu schreiben:
from myclass import MyClass from foo.bar.yourclass import YourClass
Wenn diese Schreibweise lokale Namenskonflikte verursacht, schreiben Sie sie explizit:
import myclass import foo.bar.yourclass
und verwenden Sie
myclass.MyClassundfoo.bar.yourclass.YourClass. - Wildcard-Imports (
from <module> import *) sollten vermieden werden, da sie unklar machen, welche Namen im Namensraum vorhanden sind, was sowohl Leser als auch viele automatisierte Tools verwirrt. Es gibt einen einzigen vertretbaren Anwendungsfall für einen Wildcard-Import, nämlich die Wiederveröffentlichung einer internen Schnittstelle als Teil einer öffentlichen API (z. B. Überschreiben einer reinen Python-Implementierung einer Schnittstelle mit den Definitionen aus einem optionalen Beschleunigermodul, und genau welche Definitionen überschrieben werden, ist im Voraus nicht bekannt).Bei der Wiederveröffentlichung von Namen auf diese Weise gelten die untenstehenden Richtlinien bezüglich öffentlicher und interner Schnittstellen weiterhin.
Modul-Level Dunder-Namen
Modul-Level „Dunders“ (d. h. Namen mit zwei führenden und zwei nachgestellten Unterstrichen) wie __all__, __author__, __version__ usw. sollten nach dem Modul-Docstring, aber vor allen Import-Anweisungen platziert werden, *außer* from __future__-Imports. Python schreibt vor, dass Future-Imports in einem Modul vor jedem anderen Code außer Docstrings erscheinen müssen.
"""This is the example module.
This module does stuff.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys
String-Anführungszeichen
In Python sind einzeilige Anführungszeichen und zweizeilige Anführungszeichen gleich. Dieses PEP gibt hierfür keine Empfehlung. Wählen Sie eine Regel und halten Sie sich daran. Wenn ein String jedoch ein- oder zweifache Anführungszeichen enthält, verwenden Sie das jeweils andere, um Backslashes im String zu vermeiden. Das verbessert die Lesbarkeit.
Verwenden Sie für dreifach Anführungszeichen immer doppelte Anführungszeichen, um konsistent mit der Docstring-Konvention in PEP 257 zu sein.
Leerzeichen in Ausdrücken und Anweisungen
Besondere Nervensägen
Vermeiden Sie überflüssige Leerzeichen in den folgenden Situationen:
- Unmittelbar innerhalb von Klammern, eckigen Klammern oder geschweiften Klammern.
# Correct: spam(ham[1], {eggs: 2})
# Wrong: spam( ham[ 1 ], { eggs: 2 } )
- Zwischen einem nachgestellten Komma und einer folgenden schließenden Klammer.
# Correct: foo = (0,)
# Wrong: bar = (0, )
- Unmittelbar vor einem Komma, Semikolon oder Doppelpunkt.
# Correct: if x == 4: print(x, y); x, y = y, x
# Wrong: if x == 4 : print(x , y) ; x , y = y , x
- Bei einem Slice fungiert der Doppelpunkt jedoch wie ein binärer Operator und sollte auf beiden Seiten gleich viel Platz haben (behandelt ihn als Operator mit der niedrigsten Priorität). Bei einem erweiterten Slice müssen beide Doppelpunkte den gleichen Abstand haben. Ausnahme: Wenn ein Slice-Parameter weggelassen wird, wird der Abstand weggelassen.
# Correct: ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:] ham[lower:upper], ham[lower:upper:], ham[lower::step] ham[lower+offset : upper+offset] ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)] ham[lower + offset : upper + offset]
# Wrong: ham[lower + offset:upper + offset] ham[1: 9], ham[1 :9], ham[1:9 :3] ham[lower : : step] ham[ : upper]
- Unmittelbar vor der öffnenden Klammer, die die Argumentenliste eines Funktionsaufrufs beginnt.
# Correct: spam(1)
# Wrong: spam (1)
- Unmittelbar vor der öffnenden Klammer, die eine Indizierung oder ein Slicing beginnt.
# Correct: dct['key'] = lst[index]
# Wrong: dct ['key'] = lst [index]
- Mehr als ein Leerzeichen um einen Zuweisungsoperator (oder einen anderen Operator), um ihn mit einem anderen auszurichten.
# Correct: x = 1 y = 2 long_variable = 3
# Wrong: x = 1 y = 2 long_variable = 3
Andere Empfehlungen
- Vermeiden Sie nachgestellte Leerzeichen überall. Da sie meist unsichtbar sind, können sie verwirrend sein: z. B. zählt ein Backslash gefolgt von einem Leerzeichen und einem Zeilenumbruch nicht als Zeilenfortsetzungszeichen. Einige Editoren behalten sie nicht bei, und viele Projekte (wie CPython selbst) haben Pre-Commit-Hooks, die sie ablehnen.
- Umschließen Sie diese binären Operatoren immer mit einem einzelnen Leerzeichen auf beiden Seiten: Zuweisung (
=), erweiterte Zuweisung (+=,-=etc.), Vergleiche (==,<,>,!=,<=,>=,in,not in,is,is not), Boole'sche Werte (and,or,not). - Wenn Operatoren mit unterschiedlichen Prioritäten verwendet werden, sollten Sie erwägen, um die Operatoren mit der niedrigsten Priorität Leerzeichen hinzuzufügen. Nutzen Sie Ihr eigenes Urteilsvermögen; verwenden Sie jedoch niemals mehr als ein Leerzeichen und haben Sie immer die gleiche Menge an Leerzeichen auf beiden Seiten eines binären Operators.
# Correct: i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b)
# Wrong: i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b)
- Funktionsannotationen sollten die normalen Regeln für Doppelpunkte verwenden und immer Leerzeichen um den
->-Pfeil haben, falls vorhanden. (Siehe Funktionsannotationen unten für weitere Informationen zu Funktionsannotationen.)# Correct: def munge(input: AnyStr): ... def munge() -> PosInt: ...
# Wrong: def munge(input:AnyStr): ... def munge()->PosInt: ...
- Verwenden Sie keine Leerzeichen um das Gleichheitszeichen (=), wenn es zur Angabe eines Schlüsselwortarguments oder zur Angabe eines Standardwerts für einen *unannotierten* Funktionsparameter verwendet wird.
# Correct: def complex(real, imag=0.0): return magic(r=real, i=imag)
# Wrong: def complex(real, imag = 0.0): return magic(r = real, i = imag)
Wenn Sie eine Argumentannotation mit einem Standardwert kombinieren, verwenden Sie jedoch Leerzeichen um das Gleichheitszeichen (=).
# Correct: def munge(sep: AnyStr = None): ... def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# Wrong: def munge(input: AnyStr=None): ... def munge(input: AnyStr, limit = 1000): ...
- Zusammengesetzte Anweisungen (mehrere Anweisungen in einer Zeile) werden generell nicht empfohlen.
# Correct: if foo == 'blah': do_blah_thing() do_one() do_two() do_three()
Besser nicht.
# Wrong: if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()
- Obwohl es manchmal in Ordnung ist, eine if/for/while mit einem kleinen Körper in derselben Zeile zu belassen, tun Sie dies niemals für mehrteilige Anweisungen. Vermeiden Sie es auch, solche langen Zeilen umzubrechen!
Besser nicht.
# Wrong: if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay()
Definitiv nicht.
# Wrong: 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()
Wann Nachgestellte Kommas zu verwenden sind
Nachgestellte Kommas sind normalerweise optional, außer sie sind zwingend erforderlich, wenn ein Tupel mit einem Element gebildet wird. Zur Klarheit wird empfohlen, letzteres in (technisch redundante) Klammern zu setzen.
# Correct:
FILES = ('setup.cfg',)
# Wrong:
FILES = 'setup.cfg',
Wenn nachgestellte Kommas redundant sind, sind sie oft hilfreich, wenn ein Versionskontrollsystem verwendet wird, wenn eine Liste von Werten, Argumenten oder importierten Elementen über die Zeit erweitert werden soll. Das Muster besteht darin, jeden Wert (usw.) in eine eigene Zeile zu setzen, immer ein nachgestelltes Komma hinzuzufügen und die schließende Klammer/eckige Klammer/geschweifte Klammer in der nächsten Zeile hinzuzufügen. Es ist jedoch nicht sinnvoll, ein nachgestelltes Komma in derselben Zeile wie der schließende Begrenzer zu haben (außer im oben genannten Fall von Singleton-Tupeln).
# Correct:
FILES = [
'setup.cfg',
'tox.ini',
]
initialize(FILES,
error=True,
)
# Wrong:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
Namenskonventionen
Die Namenskonventionen der Python-Bibliothek sind ein ziemliches Durcheinander, daher werden wir das nie ganz einheitlich bekommen – dennoch sind hier die derzeit empfohlenen Namensstandards. Neue Module und Pakete (einschließlich Drittanbieter-Frameworks) sollten nach diesen Standards geschrieben werden, aber wo eine bestehende Bibliothek einen anderen Stil hat, ist interne Konsistenz vorzuziehen.
Oberstes Prinzip
Namen, die für den Benutzer als öffentliche Teile der API sichtbar sind, sollten Konventionen folgen, die die Verwendung und nicht die Implementierung widerspiegeln.
Beschreibend: Namensstile
Es gibt viele verschiedene Namensstile. Es hilft, erkennen zu können, welcher Namensstil verwendet wird, unabhängig davon, wofür er verwendet wird.
Die folgenden Namensstile werden üblicherweise unterschieden:
b(einzelner Kleinbuchstabe)B(einzelner Großbuchstabe)kleingeschriebenkleingeschrieben_mit_unterstrichenGROSSGESCHRIEBENGROSSGESCHRIEBEN_MIT_UNTERSTRICHENCapitalizedWords(oder CapWords, oder CamelCase – so genannt wegen des holprigen Aussehens seiner Buchstaben [4]). Dies ist auch manchmal als StudlyCaps bekannt.Hinweis: Bei Verwendung von Akronymen in CapWords sollten alle Buchstaben des Akronyms großgeschrieben werden. Daher ist HTTPServerError besser als HttpServerError.
mixedCase(unterscheidet sich von CapitalizedWords durch den anfänglichen Kleinbuchstaben!)Capitalized_Words_With_Underscores(hässlich!)
Es gibt auch den Stil, ein kurzes eindeutiges Präfix zu verwenden, um verwandte Namen zu gruppieren. Dies wird in Python nicht viel verwendet, ist aber der Vollständigkeit halber erwähnt. Zum Beispiel gibt die Funktion os.stat() ein Tupel zurück, dessen Elemente traditionell Namen wie st_mode, st_size, st_mtime usw. haben. (Dies geschieht, um die Entsprechung mit den Feldern des POSIX-Systemaufrufsstructs hervorzuheben, was Programmierern, die damit vertraut sind, hilft.)
Die X11-Bibliothek verwendet ein führendes X für alle ihre öffentlichen Funktionen. In Python wird dieser Stil im Allgemeinen als unnötig erachtet, da Attribut- und Methodennamen mit einem Objekt vorangestellt sind und Funktionsnamen mit einem Modulnamen vorangestellt sind.
Zusätzlich werden die folgenden Sonderformen mit führenden oder nachgestellten Unterstrichen erkannt (diese können im Allgemeinen mit jeder beliebigen Fallkonvention kombiniert werden):
_single_leading_underscore: schwacher Indikator für „internen Gebrauch“. Z. B. importiertfrom M import *keine Objekte, deren Namen mit einem Unterstrich beginnen.single_trailing_underscore_: wird per Konvention verwendet, um Konflikte mit Python-Schlüsselwörtern zu vermeiden, z. B.:tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore: beim Benennen eines Klassenattributs wird Namensvermaschung (Name Mangling) aufgerufen (innerhalb der Klasse FooBar wird__boozu_FooBar__boo; siehe unten).__double_leading_and_trailing_underscore__: „magische“ Objekte oder Attribute, die in benutzerkontrollierten Namensräumen leben. Z. B.__init__,__import__oder__file__. Erfinden Sie niemals solche Namen; verwenden Sie sie nur wie dokumentiert.
Vorschreibend: Namenskonventionen
Zu vermeidende Namen
Verwenden Sie niemals die Zeichen ‚l‘ (kleiner Buchstabe el), ‚O‘ (großer Buchstabe oh) oder ‚I‘ (großer Buchstabe eye) als einzeilige Variablennamen.
In einigen Schriftarten sind diese Zeichen von den Ziffern eins und null nicht zu unterscheiden. Wenn Sie versucht sind, ‚l‘ zu verwenden, verwenden Sie stattdessen ‚L‘.
ASCII-Kompatibilität
Bezeichner, die in der Standardbibliothek verwendet werden, müssen ASCII-kompatibel sein, wie in der Richtlinienspezifikation von PEP 3131 beschrieben.
Paket- und Modulnamen
Module sollten kurze, rein kleingeschriebene Namen haben. Unterstriche können im Modulnamen verwendet werden, wenn dies die Lesbarkeit verbessert. Python-Pakete sollten ebenfalls kurze, rein kleingeschriebene Namen haben, obwohl die Verwendung von Unterstrichen nicht empfohlen wird.
Wenn ein Erweiterungsmodul, das in C oder C++ geschrieben ist, ein begleitendes Python-Modul hat, das eine übergeordnete (z. B. objektorientiertere) Schnittstelle bereitstellt, hat das C/C++-Modul einen führenden Unterstrich (z. B. _socket).
Klassennamen
Klassennamen sollten normalerweise die CapWords-Konvention verwenden.
Die Namenskonvention für Funktionen kann stattdessen in Fällen verwendet werden, in denen die Schnittstelle dokumentiert ist und hauptsächlich als aufrufbar verwendet wird.
Beachten Sie, dass es eine separate Konvention für eingebaute Namen gibt: die meisten eingebauten Namen sind einzelne Wörter (oder zwei Wörter, die miteinander verbunden sind), wobei die CapWords-Konvention nur für Ausnahmeanamen und eingebaute Konstanten verwendet wird.
Typvariablennamen
Namen von Typvariablen, die in PEP 484 eingeführt wurden, sollten normalerweise CapWords mit kurzen Namen verwenden: T, AnyStr, Num. Es wird empfohlen, Suffixe _co oder _contra an die Variablen anzuhängen, die zur Deklaration von kovarianten bzw. kontravarianten Verhalten verwendet werden.
from typing import TypeVar
VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
Ausnahnamen
Da Ausnahmen Klassen sein sollten, gilt hier die Klassennamenskonvention. Sie sollten jedoch die Endung „Error“ an Ihre Ausnahmeanamen anhängen (wenn die Ausnahme tatsächlich ein Fehler ist).
Globale Variablennamen
(Hoffen wir, dass diese Variablen nur für die Verwendung innerhalb eines Moduls bestimmt sind.) Die Konventionen sind ungefähr die gleichen wie bei Funktionen.
Module, die über from M import * verwendet werden sollen, sollten den Mechanismus __all__ verwenden, um den Export von Globale zu verhindern, oder die ältere Konvention verwenden, solche Globale mit einem Unterstrich zu versehen (was Sie vielleicht tun möchten, um anzuzeigen, dass diese Globale „Modul-nicht-öffentlich“ sind).
Funktions- und Variablennamen
Funktionsnamen sollten kleingeschrieben sein, wobei Wörter bei Bedarf durch Unterstriche getrennt werden, um die Lesbarkeit zu verbessern.
Variablennamen folgen der gleichen Konvention wie Funktionsnamen.
mixedCase ist nur in Kontexten erlaubt, in denen dies bereits der vorherrschende Stil ist (z. B. threading.py), um die Abwärtskompatibilität zu wahren.
Funktions- und Methodenargumente
Verwenden Sie immer self für das erste Argument von Instanzmethoden.
Verwenden Sie immer cls für das erste Argument von Klassenmethoden.
Wenn der Name eines Funktionsarguments mit einem reservierten Schlüsselwort kollidiert, ist es im Allgemeinen besser, einen einzelnen nachgestellten Unterstrich anzuhängen, anstatt eine Abkürzung oder Rechtschreibkorrektur zu verwenden. Daher ist class_ besser als clss. (Vielleicht besser ist es, solche Kollisionen durch die Verwendung eines Synonyms zu vermeiden.)
Methoden- und Instanzvariablennamen
Verwenden Sie die Namensregeln für Funktionen: Kleinschreibung mit durch Unterstriche getrennten Wörtern, wo nötig, um die Lesbarkeit zu verbessern.
Verwenden Sie einen führenden Unterstrich nur für nicht-öffentliche Methoden und Instanzvariablen.
Um Namenskollisionen mit Unterklassen zu vermeiden, verwenden Sie zwei führende Unterstriche, um Pythons Namensvermaschungsregeln aufzurufen.
Python vermascht diese Namen mit dem Klassennamen: Wenn die Klasse Foo ein Attribut mit dem Namen __a hat, kann es nicht über Foo.__a aufgerufen werden. (Ein insistenter Benutzer könnte immer noch darauf zugreifen, indem er Foo._Foo__a aufruft.) Im Allgemeinen sollten zwei führende Unterstriche nur verwendet werden, um Namenskonflikte mit Attributen in Klassen zu vermeiden, die für die Unterklassenbildung konzipiert sind.
Hinweis: Es gibt einige Kontroversen über die Verwendung von __names (siehe unten).
Konstanten
Konstanten werden normalerweise auf Modulebene definiert und in Großbuchstaben mit Unterstrichen zur Trennung von Wörtern geschrieben. Beispiele sind MAX_OVERFLOW und TOTAL.
Design für Vererbung
Entscheiden Sie immer, ob die Methoden und Instanzvariablen einer Klasse (zusammenfassend: „Attribute“) öffentlich oder nicht-öffentlich sein sollen. Im Zweifel wählen Sie nicht-öffentlich; es ist einfacher, sie später öffentlich zu machen, als ein öffentliches Attribut nicht-öffentlich zu machen.
Öffentliche Attribute sind solche, die Sie erwarten, dass externe Clients Ihrer Klasse verwenden, mit Ihrer Verpflichtung, keine abwärtskompatiblen Änderungen vorzunehmen. Nicht-öffentliche Attribute sind solche, die nicht von Dritten verwendet werden sollen; Sie geben keine Garantie, dass nicht-öffentliche Attribute nicht geändert oder sogar entfernt werden.
Wir verwenden hier nicht den Begriff „privat“, da in Python kein Attribut wirklich privat ist (ohne einen allgemein unnötigen Aufwand).
Eine weitere Kategorie von Attributen sind diejenigen, die Teil der „Subclass API“ sind (oft als „protected“ in anderen Sprachen bezeichnet). Einige Klassen sind so konzipiert, dass sie geerbt werden, entweder um Aspekte des Klassenverhaltens zu erweitern oder zu modifizieren. Bei der Gestaltung einer solchen Klasse sollten Sie sorgfältig entscheiden, welche Attribute öffentlich sind, welche Teil der Subclass API sind und welche wirklich nur von Ihrer Basisklasse verwendet werden sollen.
Mit diesem im Hinterkopf hier sind die pythonischen Richtlinien:
- Öffentliche Attribute sollten keine führenden Unterstriche haben.
- Wenn Ihr öffentlicher Attributname mit einem reservierten Schlüsselwort kollidiert, hängen Sie einen einzelnen nachgestellten Unterstrich an Ihren Attributnamen an. Dies ist einer Abkürzung oder einer fehlerhaften Schreibweise vorzuziehen. (Obwohl diese Regel unbeschadet dessen gilt, ist ‚cls‘ die bevorzugte Schreibweise für jede Variable oder jedes Argument, von dem bekannt ist, dass es eine Klasse ist, insbesondere das erste Argument einer Klassenmethode.)
Hinweis 1: Siehe die Empfehlung für Argumentnamen oben für Klassenmethoden.
- Bei einfachen öffentlichen Datenattributen ist es am besten, nur den Attributnamen ohne komplizierte Getter-/Setter-Methoden offenzulegen. Beachten Sie, dass Python einen einfachen Weg zur zukünftigen Erweiterung bietet, falls Sie feststellen, dass ein einfaches Datenattribut funktionale Eigenschaften benötigt. Verwenden Sie in diesem Fall Eigenschaften (properties), um die funktionale Implementierung hinter einer einfachen Datenattribut-Zugriffssyntax zu verbergen.
Hinweis 1: Versuchen Sie, das funktionale Verhalten frei von Seiteneffekten zu halten, obwohl Seiteneffekte wie Caching im Allgemeinen in Ordnung sind.
Hinweis 2: Vermeiden Sie die Verwendung von Eigenschaften für rechenintensive Operationen; die Attributnotation lässt den Aufrufer glauben, dass der Zugriff (relativ) günstig ist.
- Wenn Ihre Klasse zur Unterklassenbildung gedacht ist und Sie Attribute haben, die Sie Unterklassen nicht verwenden lassen möchten, sollten Sie diese mit zwei führenden Unterstrichen und ohne nachgestellte Unterstriche benennen. Dies ruft Pythons Namensvermaschungsalgorithmus auf, bei dem der Klassenname in den Attributnamen vermascht wird. Dies hilft, Attributnamenskollisionen zu vermeiden, falls Unterklassen versehentlich Attribute mit demselben Namen enthalten.
Hinweis 1: Beachten Sie, dass nur der einfache Klassenname im vermaschten Namen verwendet wird. Wenn eine Unterklasse also sowohl denselben Klassennamen als auch Attributnamen wählt, können Sie immer noch Namenskollisionen bekommen.
Hinweis 2: Die Namensvermaschung kann bestimmte Verwendungen, wie z. B. Debugging und
__getattr__(), weniger praktisch machen. Der Namensvermaschungsalgorithmus ist jedoch gut dokumentiert und leicht manuell durchzuführen.Hinweis 3: Nicht jeder mag Namensvermaschung. Versuchen Sie, das Bedürfnis zu vermeiden, versehentliche Namenskonflikte mit potenziellen Verwendungen durch fortgeschrittene Aufrufer abzuwägen.
Öffentliche und interne Schnittstellen
Jegliche Garantien zur Abwärtskompatibilität gelten nur für öffentliche Schnittstellen. Daher ist es wichtig, dass Benutzer klar zwischen öffentlichen und internen Schnittstellen unterscheiden können.
Dokumentierte Schnittstellen gelten als öffentlich, es sei denn, die Dokumentation erklärt sie ausdrücklich als vorläufige oder interne Schnittstellen, die von den üblichen Garantien zur Abwärtskompatibilität ausgenommen sind. Alle undokumentierten Schnittstellen sollten als intern betrachtet werden.
Um die Introspektion besser zu unterstützen, sollten Module die Namen ihrer öffentlichen API explizit mit dem Attribut __all__ deklarieren. Das Setzen von __all__ auf eine leere Liste zeigt an, dass das Modul keine öffentliche API hat.
Selbst wenn __all__ korrekt gesetzt ist, sollten interne Schnittstellen (Pakete, Module, Klassen, Funktionen, Attribute oder andere Namen) weiterhin mit einem einzelnen führenden Unterstrich beginnen.
Eine Schnittstelle gilt ebenfalls als intern, wenn ein enthaltender Namensraum (Paket, Modul oder Klasse) als intern gilt.
Importierte Namen sollten immer als Implementierungsdetail betrachtet werden. Andere Module dürfen sich nicht auf indirekten Zugriff auf solche importierten Namen verlassen, es sei denn, sie sind explizit als Teil der API des enthaltenden Moduls dokumentiert, wie z. B. os.path oder ein __init__-Modul eines Pakets, das Funktionalität aus Untermodulen freilegt.
Programmierempfehlungen
- Code sollte so geschrieben werden, dass er andere Implementierungen von Python (PyPy, Jython, IronPython, Cython, Psyco und dergleichen) nicht benachteiligt.
Verlassen Sie sich zum Beispiel nicht auf die effiziente Implementierung der In-Place-String-Verkettung von CPython für Anweisungen der Form
a += bodera = a + b. Diese Optimierung ist selbst in CPython fragil (sie funktioniert nur für einige Typen) und nicht vorhanden in Implementierungen, die keine Referenzzählung verwenden. In leistungskritischen Teilen der Bibliothek sollte die''.join()-Form verwendet werden. Dies stellt sicher, dass die Verkettung über verschiedene Implementierungen hinweg in linearer Zeit erfolgt. - Vergleiche mit Singletons wie None sollten immer mit
isoderis noterfolgen, niemals mit Gleichheitsoperatoren.Seien Sie sich auch bewusst, wenn Sie
if xschreiben, wenn Sie eigentlichif x is not Nonemeinen – z.B. beim Testen, ob eine Variable oder ein Argument, das standardmäßig None ist, auf einen anderen Wert gesetzt wurde. Der andere Wert könnte einen Typ (wie einen Container) haben, der in einem booleschen Kontext falsch sein könnte! - Verwenden Sie den
is not-Operator anstelle vonnot ... is. Obwohl beide Ausdrücke funktional identisch sind, ist der erstere besser lesbar und wird bevorzugt.# Correct: if foo is not None:
# Wrong: if not foo is None:
- Bei der Implementierung von Ordnungsoperationen mit Rich Comparisons ist es am besten, alle sechs Operationen (
__eq__,__ne__,__lt__,__le__,__gt__,__ge__) zu implementieren, anstatt sich darauf zu verlassen, dass anderer Code nur einen bestimmten Vergleich ausführt.Um den damit verbundenen Aufwand zu minimieren, bietet der Dekorator
functools.total_ordering()ein Werkzeug zur Generierung fehlender Vergleichsmethoden.PEP 207 gibt an, dass Reflexivitätsregeln von Python als gegeben vorausgesetzt werden. Somit kann der Interpreter
y > xmitx < y,y >= xmitx <= yvertauschen und die Argumente vonx == yundx != yvertauschen. Die Operationensort()undmin()verwenden garantiert den Operator<und die Funktionmax()verwendet den Operator>. Es ist jedoch am besten, alle sechs Operationen zu implementieren, damit in anderen Kontexten keine Verwirrung entsteht. - Verwenden Sie immer eine `def`-Anweisung anstelle einer Zuweisungsanweisung, die einen Lambda-Ausdruck direkt an einen Bezeichner bindet.
# Correct: def f(x): return 2*x
# Wrong: f = lambda x: 2*x
Die erste Form bedeutet, dass der Name des resultierenden Funktionsobjekts speziell 'f' anstelle des generischen '
' ist. Dies ist nützlicher für Tracebacks und Zeichenkettenrepräsentationen im Allgemeinen. Die Verwendung der Zuweisungsanweisung eliminiert den einzigen Vorteil, den ein Lambda-Ausdruck gegenüber einer expliziten `def`-Anweisung bieten kann (d. h. dass er in einen größeren Ausdruck eingebettet werden kann). - Leiten Sie Ausnahmen von
Exceptionstatt vonBaseExceptionab. Direkte Vererbung vonBaseExceptionist für Ausnahmen reserviert, bei denen deren Abfangen fast immer falsch ist.Entwerfen Sie Ausnahmehierarchien basierend auf den Unterscheidungen, die der Code beim *Abfangen* der Ausnahmen wahrscheinlich benötigt, anstatt auf den Orten, an denen die Ausnahmen ausgelöst werden. Versuchen Sie, die Frage "Was ist schief gelaufen?" programmatisch zu beantworten, anstatt nur zu sagen "Ein Problem ist aufgetreten" (siehe PEP 3151 für ein Beispiel dafür, wie diese Lektion für die integrierte Ausnahmehierarchie gelernt wurde).
Namenskonventionen für Klassen gelten hier, obwohl Sie den Suffix "Error" zu Ihren Ausnahmeklassen hinzufügen sollten, wenn die Ausnahme ein Fehler ist. Nicht-Fehler-Ausnahmen, die für nicht-lokale Flusskontrolle oder andere Formen der Signalgebung verwendet werden, benötigen keinen speziellen Suffix.
- Verwenden Sie Exception Chaining angemessen.
raise X from Ysollte verwendet werden, um einen expliziten Ersatz anzuzeigen, ohne den ursprünglichen Traceback zu verlieren.Beim bewussten Ersetzen einer inneren Ausnahme (mit
raise X from None) stellen Sie sicher, dass relevante Details auf die neue Ausnahme übertragen werden (z. B. Beibehaltung des Attributnamens bei der Konvertierung von KeyError in AttributeError oder Einbettung des Texts der ursprünglichen Ausnahme in die neue Ausnahmebotschaft). - Beim Abfangen von Ausnahmen sollten Sie spezifische Ausnahmen nennen, wann immer möglich, anstatt eine leere
except:-Klausel zu verwenden.try: import platform_specific_module except ImportError: platform_specific_module = None
Eine leere
except:-Klausel fängt SystemExit- und KeyboardInterrupt-Ausnahmen ab, was es schwieriger macht, ein Programm mit Strg-C zu unterbrechen, und kann andere Probleme verschleiern. Wenn Sie alle Ausnahmen abfangen möchten, die Programmfehler signalisieren, verwenden Sieexcept Exception:(leere except ist äquivalent zuexcept BaseException:).Eine gute Faustregel ist, die Verwendung von leeren 'except'-Klauseln auf zwei Fälle zu beschränken.
- Wenn der Exception-Handler den Traceback ausgibt oder protokolliert; zumindest wird der Benutzer darüber informiert, dass ein Fehler aufgetreten ist.
- Wenn der Code einige Aufräumarbeiten durchführen muss, die Ausnahme aber dann mit
raisenach oben weitergibt.try...finallykann für diesen Fall eine bessere Lösung sein.
- Beim Abfangen von Betriebssystemfehlern bevorzugen Sie die explizite Ausnahmehierarchie, die in Python 3.3 eingeführt wurde, gegenüber der Introspektion von
errno-Werten. - Zusätzlich gilt für alle try/except-Klauseln: Beschränken Sie die
try-Klausel auf das absolut notwendige Minimum an Code. Dies vermeidet wiederum die Maskierung von Fehlern.# Correct: try: value = collection[key] except KeyError: return key_not_found(key) else: return handle_value(value)
# Wrong: try: # Too broad! return handle_value(collection[key]) except KeyError: # Will also catch KeyError raised by handle_value() return key_not_found(key)
- Wenn eine Ressource auf einen bestimmten Codeabschnitt beschränkt ist, verwenden Sie eine
with-Anweisung, um sicherzustellen, dass sie nach der Verwendung umgehend und zuverlässig bereinigt wird. Eine `try/finally`-Anweisung ist ebenfalls akzeptabel. - Kontextmanager sollten über separate Funktionen oder Methoden aufgerufen werden, wann immer sie etwas anderes tun, als Ressourcen zu erwerben und freizugeben.
# Correct: with conn.begin_transaction(): do_stuff_in_transaction(conn)
# Wrong: with conn: do_stuff_in_transaction(conn)
Das letztere Beispiel liefert keine Informationen, die darauf hindeuten, dass die Methoden
__enter__und__exit__etwas anderes tun, als die Verbindung nach einer Transaktion zu schließen. Explizitheit ist in diesem Fall wichtig. - Seien Sie konsistent in den `return`-Anweisungen. Entweder alle `return`-Anweisungen in einer Funktion sollten einen Ausdruck zurückgeben, oder keine von ihnen sollte das tun. Wenn eine `return`-Anweisung einen Ausdruck zurückgibt, sollten alle `return`-Anweisungen, bei denen kein Wert zurückgegeben wird, dies explizit als
return Noneangeben, und am Ende der Funktion (wenn erreichbar) sollte eine explizite `return`-Anweisung vorhanden sein.# Correct: def foo(x): if x >= 0: return math.sqrt(x) else: return None def bar(x): if x < 0: return None return math.sqrt(x)
# Wrong: def foo(x): if x >= 0: return math.sqrt(x) def bar(x): if x < 0: return return math.sqrt(x)
- Verwenden Sie
''.startswith()und''.endswith()anstelle von String-Slicing, um nach Präfixen oder Suffixen zu suchen.startswith() und endswith() sind sauberer und weniger fehleranfällig.
# Correct: if foo.startswith('bar'):
# Wrong: if foo[:3] == 'bar':
- Objekttypvergleiche sollten immer mit isinstance() erfolgen, anstatt Typen direkt zu vergleichen.
# Correct: if isinstance(obj, int):
# Wrong: if type(obj) is type(1):
- Bei Sequenzen (Strings, Listen, Tupel) nutzen Sie die Tatsache, dass leere Sequenzen falsch sind.
# Correct: if not seq: if seq:
# Wrong: if len(seq): if not len(seq):
- Schreiben Sie keine String-Literale, die auf signifikante nachfolgende Leerzeichen angewiesen sind. Solche nachfolgenden Leerzeichen sind visuell nicht unterscheidbar und einige Editoren (oder neuerdings reindent.py) werden sie abschneiden.
- Vergleichen Sie keine booleschen Werte mit True oder False mittels
==.# Correct: if greeting:
# Wrong: if greeting == True:
Schlimmer
# Wrong: if greeting is True:
- Die Verwendung von Flusskontrollanweisungen
return/break/continueinnerhalb der `finally`-Suite einestry...finally, wo die Flusskontrollanweisung die `finally`-Suite verlassen würde, wird nicht empfohlen. Dies liegt daran, dass solche Anweisungen implizit jede aktive Ausnahme abbrechen, die sich durch die `finally`-Suite ausbreitet.# Wrong: def foo(): try: 1 / 0 finally: return 42
Function Annotations
Mit der Akzeptanz von PEP 484 haben sich die Stilregeln für Funktionsannotationen geändert.
- Funktionsannotationen sollten die PEP 484-Syntax verwenden (es gibt einige Formatierungsempfehlungen für Annotationen im vorherigen Abschnitt).
- Das Experimentieren mit Annotationsstilen, das zuvor in diesem PEP empfohlen wurde, wird nicht mehr gefördert.
- Außerhalb der Standardbibliothek werden nun Experimente innerhalb der Regeln von PEP 484 gefördert. Zum Beispiel das Markieren einer großen Drittanbieterbibliothek oder Anwendung mit PEP 484-Stil-Typannotationen, die Überprüfung, wie einfach es war, diese Annotationen hinzuzufügen, und die Beobachtung, ob ihre Anwesenheit die Verständlichkeit des Codes erhöht.
- Die Python-Standardbibliothek sollte konservativ bei der Übernahme solcher Annotationen sein, aber ihre Verwendung ist für neuen Code und für große Refactorings gestattet.
- Für Code, der eine andere Verwendung von Funktionsannotationen wünscht, wird empfohlen, einen Kommentar der Form einzufügen
# type: ignoream Anfang der Datei; dies weist Typ-Checker an, alle Annotationen zu ignorieren. (Feingranularere Möglichkeiten, Beschwerden von Typ-Checkern zu deaktivieren, finden Sie in PEP 484.)
- Wie Linter sind Typ-Checker optionale, separate Werkzeuge. Python-Interpreter sollten standardmäßig keine Meldungen aufgrund von Typ-Checking ausgeben und ihr Verhalten nicht aufgrund von Annotationen ändern.
- Benutzer, die keine Typ-Checker verwenden möchten, können diese ignorieren. Es wird jedoch erwartet, dass Benutzer von Drittanbieter-Bibliothekspaketen Typ-Checker über diese Pakete ausführen möchten. Zu diesem Zweck empfiehlt PEP 484 die Verwendung von Stub-Dateien: .pyi-Dateien, die vom Typ-Checker bevorzugt vor den entsprechenden .py-Dateien gelesen werden. Stub-Dateien können mit einer Bibliothek verteilt werden oder separat (mit Erlaubnis des Bibliotheksautors) über das typeshed-Repository [5].
Variablenannotationen
PEP 526 hat Variablenannotationen eingeführt. Die Stil-Empfehlungen für sie ähneln denen für Funktionsannotationen, die oben beschrieben wurden.
- Annotationen für Modul-Level-Variablen, Klassen- und Instanzvariablen sowie lokale Variablen sollten einen einzelnen Leerschritt nach dem Doppelpunkt haben.
- Vor dem Doppelpunkt sollte kein Leerzeichen sein.
- Wenn eine Zuweisung eine rechte Seite hat, sollte das Gleichheitszeichen auf beiden Seiten genau einen Leerschritt haben.
# Correct: code: int class Point: coords: Tuple[int, int] label: str = '<unknown>'
# Wrong: code:int # No space after colon code : int # Space before colon class Test: result: int=0 # No spaces around equality sign
- Obwohl PEP 526 für Python 3.6 akzeptiert wurde, ist die Syntax für Variablenannotationen die bevorzugte Syntax für Stub-Dateien in allen Python-Versionen (siehe PEP 484 für Details).
Fußnoten
Referenzen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0008.rst
Zuletzt geändert: 2025-04-04 00:19:04 GMT
Kommentare
Kommentare, die dem Code widersprechen, sind schlimmer als keine Kommentare. Machen Sie es sich immer zur Priorität, die Kommentare bei Codeänderungen auf dem neuesten Stand zu halten!
Kommentare sollten vollständige Sätze sein. Das erste Wort sollte großgeschrieben werden, es sei denn, es handelt sich um einen Bezeichner, der mit einem Kleinbuchstaben beginnt (ändern Sie niemals die Groß-/Kleinschreibung von Bezeichnern!).
Blockkommentare bestehen im Allgemeinen aus einem oder mehreren Absätzen, die aus vollständigen Sätzen aufgebaut sind, wobei jeder Satz mit einem Punkt endet.
Sie sollten ein oder zwei Leerzeichen nach einem Satzende-Punkt in mehrsätzigen Kommentaren verwenden, außer nach dem letzten Satz.
Stellen Sie sicher, dass Ihre Kommentare klar und für andere Sprecher der Sprache, in der Sie schreiben, leicht verständlich sind.
Python-Coder aus nicht-englischsprachigen Ländern: Bitte schreiben Sie Ihre Kommentare auf Englisch, es sei denn, Sie sind zu 120 % sicher, dass der Code niemals von Personen gelesen wird, die Ihre Sprache nicht sprechen.
Blockkommentare
Blockkommentare beziehen sich im Allgemeinen auf einen Teil (oder den gesamten) folgenden Codes und sind auf der gleichen Ebene wie dieser Code eingerückt. Jede Zeile eines Blockkommentars beginnt mit einem
#und einem einzelnen Leerzeichen (es sei denn, es handelt sich um eingerückten Text innerhalb des Kommentars).Absätze innerhalb eines Blockkommentars werden durch eine Zeile mit einem einzelnen
#getrennt.Inline-Kommentare
Verwenden Sie Inline-Kommentare sparsam.
Ein Inline-Kommentar ist ein Kommentar in derselben Zeile wie eine Anweisung. Inline-Kommentare sollten mindestens zwei Leerzeichen von der Anweisung getrennt sein. Sie sollten mit einem # und einem einzelnen Leerzeichen beginnen.
Inline-Kommentare sind unnötig und tatsächlich ablenkend, wenn sie das Offensichtliche wiederholen. Tun Sie das nicht.
Aber manchmal ist das nützlich.
Docstrings
Konventionen zum Schreiben guter Dokumentationszeichenfolgen (auch „Docstrings“ genannt) sind in PEP 257 verewigt.
def-Zeile erscheinen.""", die einen mehrzeiligen Docstring beendet, auf einer eigenen Zeile steht."""in derselben Zeile."""Return an ex-parrot."""