PEP 8 – Die Schönheit von Python

Mein erster Blog-Eintrag sollte ein Eintrag sein, den man immer und immer wieder erleben kann – ein Eintrag, der nicht langweilig wird – nun ja langweilig mag er werden, aber er sollte definitiv nicht so leicht zu merken sein, dass man in seiner professionellen Laufbahn nicht noch einmal drauf schauen möchte. Als Python Enthusiast gibt es für mich kein besseres erstes Thema als ein PEP (Python Enhancement Proposal) – zu Deutsch „Vorschlag zur Python-Verbesserung“ – ein Designdokument, das der Python-Community Informationen liefert oder ein neues Feature für Python, seine Prozesse oder Umgebung beschreibt.

Und welches PEP ist schöner als PEP 8?

PEP 8 das, wie der Name schon sagt, 8. PEP mit dem Titel „Style Guide für Python-Code“ – darin werden die wichtigsten Stil-Vorschläge beschrieben und erläutert.
In meinem Post möchte ich auf möchlichst alle Vorschläge aus PEP 8 eingehen und mit Code-Beispielen erläutern.

Der Besitz eines Style Guides ist überaus wichtig, sobald jemand den geschrieben Code lesen soll. Normalerweise schreibt man Code, damit jemand ihn nutzt, davon profitiert und ggf. daran weiterarbeitet oder dadurch etwas neues lernt. Code ist nicht einfach nur einmal geschrieben und nie wieder mehr gelesen, denn:

“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. [Therefore,] making it easy to read makes it easier to write.”

Wahrlich das Verhältnis von Zeitaufwand zum Lesen und Schreiben liegt weit über 10 zu 1. Wir lesen ständig alten Code als Teil der Bemühungen, neuen Code zu schreiben. …. [Daher] ist es einfacher zu schreiben, wenn es sich leicht liest.

Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

Python, als eine Sprache mit einer Community, die sehr viel Wert auf Ästhetik legt, hat glücklicherweise einen offiziellen Style Guide, den man immer beachten sollte, außer das Team worin man arbeitet nutzt einen eigenen Style Guide. Als bekanntes Beispiel kann man Googles Python Style Guide sehen, den man nur nutzen sollte, wenn man an Google-Projekten arbeitet oder wenn das eigene Team/Unternehmen sich dazu entschlossen hat den Google-Standard zu nutzen.

Sollte man keinen Style Guide nutzen, ist es dringlichst empfohlen in Zusammenarbeit mit den Mitarbeitern einen auszusuchen! Ohne Style Guide ist das Debuggen, Verbessern, Erweitern immens schwer – natürlich gibt es außer dem Style Guide noch viele andere Dinge, die man als professioneller Programmierer beachten muss. Es gibt neben dem Stil natürlich auch Code-Architektur, generelle Prinzipien für Code-Qualität und vieles mehr, was ich in Zukunft angehen möchte.

Dieser Post kann grundsätzlich als eine freie Übersetzung und Kommentierung des PEP 8-Eintrages der Python-Community gesehen werden.


Einleitung

PEP 8 enthält die Coding-Konventionen für Python-Code, der die Standardbibliothek in der Haupt-Python-Distribution umfasst. Beachtet ggf. die begleitende informative PEP, die Stilrichtlinien für C-Code in der C-Implementierung von Python beschreibt.

PEP8 und PEP 257 (Docstring Conventions) wurden von Guido van Rossums erstem Python Style Guide Essay übernommen, mit einigen Ergänzungen aus Barry Warsaws Style Guide.

Dieser Style Guide entwickelt sich im Laufe der Zeit weiter, da zusätzliche Konventionen identifiziert werden und vergangene Konventionen durch Änderungen in der Sprache selbst obsolet werden.

Viele Projekte haben ihre eigenen Codierungsstilrichtlinien. Im Falle von Konflikten haben solche projektspezifischen Leitfäden für dieses Projekt Vorrang.

Übersicht

Eine kurze Übersicht über alle PEP 8 Regeln. Natürlich soll die Übersicht keine komplette Anleitung sein, sie versucht nur kurz und bündig zusammenzufassen.

Für Beispiele, Erklärungen und mehr Informationen, könnt ihr einfach weiterlesen.

Nr. Regel Bedeutung
1 Identation 4 Leerzeichen, keine Tabs!
2 Maximale Zeilenlänge – 79 Chars für Code
– 72 Chars für Commentare, Docstrings
Heutzutage nutzt man normalerweise mehr, das ist sehr teamspezifisch
3 Zeilenumbrüche bei Operatornutzung Ein Zeilenumbruch sollte vor einem Operator erscheinen
4 Leerzeilen – Top-Level-Funktionen und Klassenfunktionen müssen mit zwei leeren Zeilen umgeben sein
– Methoden Definitionen innerhalb von Klassen werden mit einer Leerzeile umgeben
– Ggf. weitere Leerzeile, um Gruppen zu trennen
5 Kodierung der Quelldatei – Code im Core sollte immer UTF-8 sein (oder ASCII in Python2)
– Dateien, die ASCII (Python2) oder UTF-8 (Python3) nutzen, sollten keine Kodierungdeklaration haben.
6 Imports – Ein Import pro Zeile, außer bei from X import y
– Immer am Anfang der Datei (nach Kommentaren und Docstrings)
– Absolute imports sind empfohlen
– Wildcard imports (from import *) sollten nicht genutzt werden
7 Dunder Namen – Nach den Module-Docstrings, aber vor den Imports
– Aber trotzdem nach from __future__ import <>
8 Anführungszeichen – ‚ und „, sind beide akzeptable
– Man sollte aber immer beim ausgewähltem bleiben
– Bei docstrings sollte man ausschließlich doppelte Anführungszeichen nutzen (PEP 257)
9 Leerzeichen Siehe Leerzeichen

1. Einrückung

Verwende 4 Leerzeichen pro Einrückungsebene.

Fortsetzungszeilen sollten umhüllte Elemente entweder vertikal mit der impliziten Linie von Python ausrichten, die in Klammern (), eckigen Klammern [] oder geschweifte Klammern {} zusammengefügt wird, oder mit einer hängenden Einrückung. Bei der Verwendung einer hängenden Einrückung ist folgendes zu beachten: In der ersten Zeile sollten keine Argumente vorhanden sein und weitere Einzüge sollten verwendet werden, um sich klar als Fortsetzungszeile zu unterscheiden.

Ja:

# 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)

Nein:

# 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 optional bei Fortsetzungszeilen.

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 verlangen zu können, dass diese über mehrere Zeilen geschrieben wird, ist es erwähnenswert, dass die Kombination aus einem zweistelligen Schlüssenwort (z.B. if), einem Leerzeichen und einer öffnenden Klammer, automatisch eine 4-Leerzeichen-Einrückung für die nächsten Zeilen erstellt.

Dieses Feature (not a Bug!) kann zu visuellen Konflikten mit der eingerückten Codefolge innerhalb der if-Anweisungführen, die automatisch auch mit 4 Stellen eingerückt wäre. PEP 8 nimmt keine explizite Position ein, wie (oder ob) solche bedingten Linien weiter visuell von der verschachtelten Suite innerhalb der if-Anweisungunterschieden werden sollen. Zu den akzeptablen Optionen in solchen Situationen gehören, sind aber nicht beschränkt auf:

# 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()

Gerne auch die Diskussion unter #Zeilenumbrüche bei Operatornutzung lesen.

Die abschließende Klammer bei mehrzeiligen Konstrukten kann sich entweder unter dem ersten Nicht-Leerzeichen der letzten Zeile der Liste wie in:

my_list = [
    1, 2, 3,
    4, 5, 6,
    ]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )

oder es kann unter dem ersten Zeichen der Zeile, die das mehrzeilige Konstrukt startet, aufgereiht sein, wie in:

my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

2.1 Tabs oder Leerzeichen?

Leerzeichen sind die bevorzugte Einrückungsmethode.

Tabs sollten nur verwendet werden, um mit Code konsistent zu bleiben, der bereits mit Tabs eingerückt ist.

Python3 erlaubt es nicht, die Verwendung von Tabs und Leerzeichen für die Einrückung zu vermischen.

Python2-Code, der mit einer Mischung aus Tabs und Leerzeichen eingerückt ist, sollte in die ausschließliche Verwendung von Leerzeichen umgewandelt werden.

Wenn der Python2-Befehlszeileninterpreter mit der Option -t aufgerufen wird, gibt er Warnungen über Code aus, der Tabs und Leerzeichen illegal vermischt. Bei der Verwendung von -tt werden diese Warnungen zu Fehlern. Diese Optionen sind sehr empfehlenswert!

2. Maximale Zeilenlänge

Alle Zeilen sollte auf 79 Zeichen begrenzt werden.

Für lange Textblöcke mit weniger strukturellen Einschränkungen (Dokumente oder Kommentare) sollte die Zeilenlänge auf 72 Zeichen begrenzt 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 standardmäßige Einbettung in die meisten Tools stört die visuelle Struktur des Codes und erschwert das Verständnis. Die Grenzen werden so gewählt, dass bei Editoren mit einer Fensterbreite von 80 kein Umbruch stattfindet, auch wenn das Tool beim Umbruch von Zeilen eine Markierungssilbe in der letzten Spalte platziert. Einige webbasierte Tools bieten möglicherweise überhaupt keinen dynamischen Zeilenumbruch.

Einige Teams favorisieren eine längere Zeilenlänge. Für Code, der ausschließlich oder hauptsächlich von einem Team gepflegt wird, das sich in dieser Angelegenheit einigen kann, ist es in Ordnung, die nominale Zeilenlänge von 80 auf 100 Zeichen zu erhöhen (was die maximale Länge auf 99 Zeichen erhöht), vorausgesetzt, dass Kommentare und Dokumentierungen noch mit 72 Zeichen ummantelt sind.

Die Python-Standardbibliothek ist konservativ und erfordert eine Begrenzung der Zeilen auf 79 Zeichen (und der Docstrings/Kommentare auf 72), deshalb muss jeder, der im Python-Projekt mitwirken möchte, die 79-Zeichen-Regel befolgen.

Die bevorzugte Art, lange Zeilen zu umbrechen, ist die Verwendung von Pythons impliziter Zeilenfortsetzung innerhalb von allen Klammerarten. Lange Zeilen können über mehrere Zeilen gebrochen werden, indem Ausdrücke in Klammern eingeschlossen werden. Diese sollten anstelle eines Backslash für die Zeilenfortsetzung verwendet werden.

Backslashes können manchmal noch angemessen sein. Beispielsweise können lange, mehrere mit Anweisungen keine implizite Fortsetzung verwenden, so dass Backslashes akzeptabel sind:

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())

Ein weiterer solcher Fall ist bei assert-Anweisung.

Achtet darauf, dass die fortlaufende Zeile entsprechend eingerückt ist.

3. Zeilenumbrüche bei Operatornutzung

Eine gute Merkregel für korrekte Zeilenumbrüche bei Operatornutzung, wäre sich einfach die standarmäßige mathematische Darstellung zu nutzen.

Ja:

income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

Donald Knuth erklärt die traditionelle Regel in seiner Reihe „Computers and Typesetting“: „Obwohl Formeln innerhalb eines Absatzes immer nach binären Operationen und Beziehungen unterbrochen werden, werden angezeigte Formeln immer vor binären Operationen unterbrochen.“

Nein:

income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

Im Python-Code ist es zulässig, vor oder nach einem binären Operator zu brechen, solange die Konvention lokal konsistent ist. Für neuen Code wird der Stil von Knuth vorgeschlagen.

4. Leerzeilen

Umgebe die oberste Funktions- und Klassendefinition mit zwei Leerzeilen.

Methodendefinitionen innerhalb einer Klasse werden von einer einzigen Leerzeile umgeben.

Zusätzliche Leerzeilen können (sparsam) verwendet werden, um Gruppen von verwandten Funktionen zu trennen. Leerzeilen können zwischen einem Haufen verwandter Einzeiler (z.B. einer Reihe von Dummy-Implementierungen) weggelassen werden.

Verwende Leerzeilen in Funktionen sparsam, um logische Abschnitte zu kennzeichnen.

Python akzeptiert Control-L (d.h. ^L) Form Feed Zeichen als Leerzeichen; Viele Tools behandeln dieses Zeichen als Seitentrenner, so dass man damit Seiten von verwandten Abschnitten der Datei trennen kann. Zu beachten ist, dass einige Editoren und webbasierte Code-Betrachter control-L möglicherweise nicht als Formular-Feed erkennen und an seiner Stelle ein anderes Silbenzeichen anzeigen.

5. Kodierung der Quelldatei

Grundsätzlich sollte man bei Python3 immer UTF-8 nutzen, bei Python2 ASCII. Wenn man die empfohlene Kodierung nutzt, sollte man die Kodierung nicht extra deklarieren.

In der Standardbibliothek sollten nicht-standardmäßige Kodierungen nur zu Testzwecken verwendet werden oder wenn ein Kommentar oder ein Docstring einen Autorennamen erwähnen muss, der Nicht-ASCII-Zeichen enthält; andernfalls ist die Verwendung von \x, \u, \U, \U oder \N Escapes der bevorzugte Weg, um Nicht-ASCII-Daten in Zeichenkettenliteralen aufzunehmen.

Für Python 3.0 und darüber hinaus ist für die Standardbibliothek die folgende Richtlinie vorgeschrieben (siehe PEP 3131): Alle Bezeichner in der Python-Standardbibliothek müssen nur ASCII-Bezeichner verwenden, und sollten, wo immer möglich, englische Wörter verwenden (in vielen Fällen werden Abkürzungen und Fachbegriffe verwendet, die nicht Englisch sind). Darüber hinaus müssen Stringliterale und Kommentare ebenfalls in ASCII vorliegen. Die einzigen Ausnahmen sind

  • Testfälle, die die Nicht-ASCII-Funktionen testen
  • Namen von Autoren. Verfasser, deren Namen nicht auf dem lateinischen Alphabet basieren (lateinisch-1, ISO/IEC 8859-1 Zeichensatz), müssen eine Transliteration ihrer Namen in diesem Zeichensatz angeben.

Open-Source-Projekte mit einem globalen Publikum werden angehalten, eine ähnliche Politik zu verfolgen.

6. Imports

6.1 Imports sollten auf eigenen Zeilen stehen

Yes: import os
     import sys

No:  import sys, os

Das hier ist aber auch akzeptabel:

from subprocess import Popen, PIPE

6.2 Imports sollten immer oben stehen

Imports werden immer ganz oben in der Datei platziert, direkt nach jedem Modulkommentar und den Docstrings, vor den Modulglobalen und Konstanten.

Importe sollten in der folgenden Reihenfolge zusammengefasst werden:

  1. Standardbibliotheken importe
  2. Importe von nahestehenden Drittanbietern
  3. Lokale Anwendung / bibliotheksspezifische Importe

Es sollte eine Leerzeile zwischen jeder Gruppe von Importen eingefügt werden.

6.3 Absolute importe sind empfohlen

Absolute Importe werden empfohlen, da sie in der Regel besser lesbar sind und bei falscher Konfiguration des Importsystems (z.B. wenn ein Verzeichnis innerhalb eines Pakets auf sys.path landet) tendenziell ein besseres Verhalten zeigen (oder zumindest bessere Fehlermeldungen geben):

import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example

Allerdings sind explizite relative Importe eine akzeptable Alternative zu absoluten Importen, insbesondere bei komplexen Paketlayouts, bei denen die Verwendung von absoluten Importen unnötig umfangreich wäre:

from . import sibling
from .sibling import example

Standard-Bibliothekscode sollte komplexe Paketlayouts vermeiden und immer absolute Importe verwenden.

Implizite relative Importe sollten niemals verwendet werden und wurden in Python 3 entfernt.

6.4 Klassen enthaltendes Module

Beim Import einer Klasse aus einem klassenhaltigen Modul ist es normalerweise in Ordnung, dies zu schreiben:

from myclass import MyClass
from foo.bar.yourclass import YourClass

Wenn diese Schreibweise zu Konflikten zwischen lokalen Namen führt, dann schreibt man sie explizit:

import myclass
import foo.bar.yourclass

und verwende myclass.MyClass und foo.bar.yourclass.YourClass.

6.5 Wildcard imports

Wildcard-Importe (from <module> import *) sollten vermieden werden, da sie unklar machen, welche Namen im Namensraum vorhanden sind, was sowohl die Leser als auch viele automatisierte Tools verwirrt. Es gibt einen vertretbaren Anwendungsfall für einen Wildcard-Import, nämlich die Wiederveröffentlichung eines internen Interfaces als Teil einer öffentlichen API (z.B. das Überschreiben einer reinen Python-Implementierung eines Interfaces mit den Definitionen eines optionalen Accelerator-Moduls ohne vorherige Kenntnis der genauen zu überschreibenden Definitionen).

Bei der Neuveröffentlichung von Namen auf diese Weise gelten weiterhin die folgenden Richtlinien für öffentliche und interne Schnittstellen.

7. Dunder Namen

Dunders auf Modulebene (d.h. Namen mit zwei führenden und zwei nachgeordneten Unterstrichen) wie __all__, __author__, __version__, etc. sollten nach der Moduldokumentation, aber vor allen Importanweisungen mit Ausnahme von __future__ Importen platziert werden. Python schreibt vor, dass Future-Importe im 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

8. Anführungszeichen

In Python sind einfach angeführte Strings und doppelt angeführte Strings identisch. Dieser PEP gibt keine Empfehlung dazu ab. Wählt eine Regel und haltet euch daran. Wenn eine Zeichenkette jedoch einfache oder doppelte Anführungszeichen enthält, verwendet das andere, um Backslashes in der Zeichenkette zu vermeiden. Es verbessert die Lesbarkeit.

Verwenden Sie bei Zeichenketten mit drei Anführungszeichen immer doppelte Anführungszeichen, um mit der Docstring-Konvention in PEP 257 konsistent zu sein.

9. Leerzeichen

9.1 Direkt in Klammern

Ja: spam(ham[1], {eggs: 2})
Nein: spam( ham[ 1 ], { eggs: 2 } )

9.2 Zwischen letztem Komma und schließender Klammer

Ja: foo = (0,)
Nein: bar = (0, )

9.3 Unmittelbar vor einem Komma, Semikolon oder Doppelpunkt

Ja: if x == 4: print x, y; x, y = y, x
Nein: if x == 4 : print x , y ; x , y = y , x

9.4 In Slices

In einem Slice verhält sich der Doppelpunkt jedoch wie ein binärer Operator und sollte auf beiden Seiten gleiche Mengen aufweisen (er wird als der Operator mit der niedrigsten Priorität behandelt). In einem erweiterten Slice müssen beide Doppelpunkte den gleichen Abstand aufweisen. Ausnahme: Wenn ein Slice-Parameter weggelassen wird, wird der Platz weggelassen In einem Slice verhält sich der Doppelpunkt jedoch wie ein binärer Operator und sollte auf beiden Seiten gleiche Mengen aufweisen (er wird als der Operator mit der niedrigsten Priorität behandelt). In einem erweiterten Slice müssen beide Doppelpunkte den gleichen Abstand aufweisen. Ausnahme: Wenn ein Slice-Parameter weggelassen wird, wird der Platz weggelassen

Ja:

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]

Nein:

ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]

9.5 Unmittelbar vor der offenen Klammer, die die Argumentenliste eines Funktionsaufrufs startet

Ja: foo(1)
Nein: bar (1)

9.6 Unmittelbar vor der offenen Klammer, die eine Indexierung oder ein Slicing startet:

Ja: dct['key'] = lst[index]
Nein: dct ['key'] = lst [index]

9.7 Mehr als ein Leerzeichen um einen zugewiesenen (oder anderen) Operator herum, um ihn miteinander auszurichten

Ja:

x = 1
y = 2
long_variable = 3

Nein:

x             = 1
y             = 2
long_variable = 3

10. Weitere Vorschläge

10.1 Allgemein

  • Vermeidet überall nachschleppende Leerzeichen
  • Folgende Operatoren immer mit einem Leerzeichen umgeben
    • Zuweisungen (=)
    • Erweiterte Zuweisungen (+=, -=, etc.)
    • Vergleiche (==, <, >, !=, <>, <=, >=, in, not in, is, is not)
    • Bool’sche Ausdrücke (and, or, not)

10.1.1 Operatoren mit unterschiedlichen Prioritäten

Wenn Operatoren mit unterschiedlichen Prioritäten verwendet werden, empfiehlt es sich, Leerzeichen um die Operatoren mit der niedrigsten Priorität(en) hinzuzufügen. Verwendet euer eigenes Urteilsvermögen; jedoch nie mehr als ein Leerzeichen und habt immer die gleiche Menge an Leerzeichen auf beiden Seiten eines binären Operators.

Ja:

i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)i = i + 1

Nein:

i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

10.1.2 Funktionskommentare

Funktionsanmerkungen sollten die normalen Regeln für Doppelpunkte verwenden und immer Leerzeichen um den -> Pfeil herum haben, falls vorhanden. Weitere Informationen über Funktionskommentare enthält der Abschnitt #Funktionsbeschreibung.

Ja:

def munge(input: AnyStr): ...
def munge() -> AnyStr: ...

Nein:

def munge(input:AnyStr): ...
def munge()->PosInt: ...

10.1.3 Keine Leerzeichen in Argumenten

Benutze keine Leerzeichen um das Zeichen =, wenn es zur Angabe eines Schlüsselwortarguments verwendet wird, oder wenn es zur Angabe eines Standardwertes für einen nicht kommentierten Funktionsparameter verwendet wird.

Ja:

def complex(real, imag=0.0):
    return magic(r=real, i=imag)

Nein:

def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

Wenn man jedoch eine Argumentannotation mit einem Standardwert kombiniert, verwendet Leerzeichen um das = Zeichen herum:

Ja:

def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...

Nein:

def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...

10.1.4 Keine zusammengesetzten Anweisungen

Ja:

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()

10.1.5 Anweisungen in einer Zeile

Während es manchmal in Ordnung ist, ein if/for/while mit einem kleinen Anweisungsteil auf die gleiche Zeile zu setzen, sollte dies bei Mehrsatzanweisungen nie geschehen. Vermeidet auch das Falten so langer Linien!

Lieber nicht:

if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t &lt; 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()

10.2 Folgekommas

Nachfolgende Kommas sind in der Regel optional, außer wenn ein Tupel aus einem Element gebildet wird (und in Python 2 haben sie eine Semantik für die Print-Anweisung). Aus Gründen der Übersichtlichkeit wird empfohlen, letztere in (technisch redundante) Klammern zu setzen.

Ja:

FILES = ('setup.cfg',)

Okay, aber verwirrend:

FILES = 'setup.cfg',

Wenn Nachkommas redundant sind, sind sie oft hilfreich, wenn ein Versionskontrollsystem verwendet wird, bei dem erwartet wird, dass eine Liste von Werten, Argumenten oder importierten Elementen im Laufe der Zeit erweitert wird. Das Muster besteht darin, jeden Wert (usw.) einzeln auf eine Zeile zu setzen, wobei immer ein abschließendes Komma hinzugefügt wird, und die schließende Klammer in der nächsten Zeile hinzuzufügen. Es ist jedoch nicht sinnvoll, ein nachfolgendes Komma in der gleichen Zeile wie das abschließende Trennzeichen zu haben (außer im obigen Fall von Singleton-Tupeln).

Ja:

FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )

Nein:

FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

10.3 Kommentare

Kommentare, die dem Code widersprechen, sind schlimmer als keine Kommentare. Achte immer darauf, die Kommentare auf dem neuesten Stand zu halten, wenn sich der Code ändert!

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 (ändert niemals die Schreibweise von Bezeichnern!).

Blockkommentare bestehen im Allgemeinen aus einem oder mehreren Absätzen, die aus vollständigen Sätzen aufgebaut sind, wobei jeder Satz in einem Zeitraum endet.

Bei mehrsätzigen Kommentaren empfiehlt es sich, nach einem Punkt zwei Leerzeichen zu verwenden, außer nach dem letzten Satz.

Wenn du Englisch schreibst, folge Strunk and White.

Python-Programmierer aus nicht englischsprachigen Ländern: Bitte schreibt eure Kommentare auf Englisch, es sei denn, ihr seid euch zu 120% sicher, dass der Code niemals von Personen gelesen wird, die eure Sprache nicht sprechen.

10.3.1 Block-Kommentare

Block-Kommentare gelten im Allgemeinen für einige (oder alle) folgenden Codezeilen 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.

10.3.2 Inline-Kommentare

Sparsamer Einsatz von Inline-Kommentaren ist empfehlenswert.

Ein Inline-Kommentar ist ein Kommentar in der gleichen Zeile wie eine Anweisung. Inline-Kommentare sollten durch mindestens zwei Leerzeichen von der Anweisung getrennt sein. Sie sollten mit einem # und einem einzelnen Leerzeichen beginnen.

Inline-Kommentare sind unnötig und in der Tat ablenkend, wenn sie das Offensichtliche enthalten. Tu das nicht:

x = x + 1                 # Increment x

Aber manchmal macht das hier Sinn:

x = x + 1                 # Compensate for border

10.3.3 Dokumentations-Strings (Docstrings)

Konventionen zum Schreiben guter Dokumentationszeichenketten (auch bekannt als „docstrings“) sind in PEP 257 verewigt.

Verfasse Docstrings für alle öffentlichen Module, Funktionen, Klassen und Methoden. Docstrings sind für nicht-öffentliche Methoden nicht notwendig, aber Sie sollten einen Kommentar haben, der beschreibt, was die Methode tut. Dieser Kommentar sollte nach der Def-Zeile erscheinen.

PEP 257 beschreibt gute Docstring-Konventionen. Am wichtigsten ist, dass das „““, das eine mehrzeilige Docstring beendet, in einer eigenen Zeile stehen sollte:

"""Return a foobang

Optional plotz says to frobnicate the bizbaz first.
"""

Bei einzeiligen Docstrings halte bitte das Schließen „““ auf der gleichen Zeile.

10.4 Namenskonventionen

Die Namenskonventionen der Python-Bibliothek sind ein wenig durcheinander, so dass man dies nie vollständig konsistent bekommen wird – dennoch hier sind die derzeit empfohlenen Namensstandards. Neue Module und Pakete (einschließlich Frameworks von Drittanbietern) sollten nach diesen Standards geschrieben werden, aber wenn eine bestehende Bibliothek einen anderen Stil hat, wird die interne Konsistenz bevorzugt.

10.4.1 Vorrangiges 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.

10.4.2 Beschreibend: Benennungsstile

Es gibt viele verschiedene Namensstile. Es hilft zu erkennen, welcher Namensstil verwendet wird, unabhängig davon, wofür er verwendet wird.

Die folgenden Benennungsstile werden häufig unterschieden:

  • b (single lowercase letter)
  • B (single uppercase letter)
  • lowercase
  • lower_case_with_underscores
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CapitalizedWords (or CapWords, or CamelCase — so named because of the bumpy look of its letters). This is also sometimes known as StudlyCaps.Note: When using acronyms in CapWords, capitalize all the letters of the acronym. Thus HTTPServerError is better than HttpServerError.
  • mixedCase (differs from CapitalizedWords by initial lowercase character!)
  • Capitalized_Words_With_Underscores (ugly!)

Es gibt auch den Stil, ein kurzes eindeutiges Präfix zu verwenden, um verwandte Namen zusammenzufassen. Dies wird in Python nicht oft verwendet, wird 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 und so weiter haben. (Dies geschieht, um die Übereinstimmung mit den Feldern der POSIX-System-Aufrufstruktur zu betonen, die Programmierern hilft, die damit vertraut sind.)

Die X11-Bibliothek verwendet für alle ihre öffentlichen Funktionen ein führendes X. In Python wird dieser Stil allgemein als unnötig erachtet, da Attribut- und Methodennamen mit einem Objekt- und Funktionsnamen mit einem Modelnamen vorangestellt sind.

Darüber hinaus werden folgende Sonderformen mit vor- oder nachlaufenden Unterstrichen erkannt (diese können in der Regel mit einer beliebigen Fallkonvention kombiniert werden):

  • _single_leading_underscore: weak „internal use“ indicator. E.g. from M import * does not import objects whose name starts with an underscore.
  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g.
    • Tkinter.Toplevel(master, class_='ClassName')
  • __double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).
  • __double_leading_and_trailing_underscore__: „magic“ objects or attributes that live in user-controlled namespaces. E.g. __init____import__ or __file__. Never invent such names; only use them as documented.

10.5 Verschreibend: Namenskonventionen

10.5.1 Zu vermeidende Namen

Benutze niemals die Zeichen ‚l‘ (Kleinbuchstabe el), ‚O‘ (Großbuchstabe oh) oder ‚I‘ (Großbuchstabe i) als einzelnes Zeichen für Variablennamen.

In einigen Schriftarten sind diese Zeichen von den Ziffern eins und null nicht zu unterscheiden. Wenn du versucht bist, ‚l‘ zu benutzen, benutze stattdessen ‚L‘.

10.5.2 ASCII-Kompatibilität

Die in der Standardbibliothek verwendeten Bezeichner müssen ASCII-kompatibel sein, wie im Richtlinienabschnitt von PEP 3131 beschrieben.

10.5.3 Paket- und Modulnamen

Module sollten kurze, klein geschriebene Namen haben. Unterstriche können im Modulnamen verwendet werden, wenn sie die Lesbarkeit verbessern. Python-Pakete sollten auch kurze, ausschließlich klein geschriebene Namen haben, allerdings wird die Verwendung von Unterstrichen abgeraten.

Wenn ein in C oder C++ geschriebenes Erweiterungsmodul ein zugehöriges Python-Modul hat, das eine höherwertige (z.B. mehr objektorientierte) Schnittstelle bereitstellt, hat das C/C++-Modul einen führenden Unterstrich (z.B. _socket).

10.5.3 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 und primär als Aufrufer verwendet wird.

Es gibt eine separate Konvention für eingebaute Namen: Die meisten integrierten Namen sind einzelne Wörter (oder zwei Wörter laufen zusammen), wobei die CapWords-Konvention nur für Ausnahmenamen und eingebaute Konstanten verwendet wird.

10.5.4 Typ Variablenbezeichnungen

Namen von Typvariablen, die in PEP 484 eingeführt werden, sollten normalerweise CapWords verwenden, die kurze Namen bevorzugen: T, AnyStr, Num. Es wird empfohlen, den Variablen, die zur Deklaration von Kovarianten- oder Kontravariantenverhalten verwendet werden, die Suffixe _co oder _contra hinzuzufügen:

from typing import TypeVar

VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
10.5.5 Namen Exceptions

Da Ausnahmen Klassen sein sollten, gilt hier die Namenskonvention der Klasse. Sie sollten jedoch das Suffix „Error“ für Ihre Exception-Namen verwenden (wenn die Exception tatsächlich ein Fehler ist).

10.5.6 Globale Variablennamen

(Hoffentlich sind diese Variablen nur für die Verwendung innerhalb eines Moduls gedacht.) Die Konventionen sind etwa die gleichen wie bei Funktionen.

Module, die für die Verwendung über den M-Import * konzipiert sind, sollten den all-Mechanismus verwenden, um den Export von Globals zu verhindern, oder die ältere Konvention verwenden, solche Globals mit einem Unterstrich zu versehen (was man tun sollte, um anzuzeigen, dass diese Globals „module non-public“ sind).

10.5.7 Funktions- und Variablennamen

Funktionsnamen sollten klein geschrieben sein, wobei die Wörter durch Unterstriche getrennt sein sollten, 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 erhalten.

10.5.8 Funktions- und Methodenargumente

Benutze immer self für das erste Argument, um Methoden zu instanziieren.

Verwende 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 nachlaufenden Unterstrich anzuhängen, als eine Abkürzung oder Rechtschreibfehler zu verwenden. Somit ist class_ besser als clss. (Vielleicht ist es besser, solche Konflikte zu vermeiden, indem man ein Synonym verwendet.)

10.5.9 Methodennamen und Instanzvariablen

Zur besseren Lesbarkeit sollte die Funktion Benennungsregeln verwendet werden: Kleinbuchstaben mit Wörtern, die bei Bedarf durch Unterstriche getrennt sind.

Benutze nur einen führenden Unterstrich für nicht-öffentliche Methoden und Instanzvariablen.

Um Namenskonflikte mit Unterklassen zu vermeiden, sollten Sie zwei führende Unterstriche verwenden, um Pythons Regeln zur Namensverzerrung aufzurufen.

Python vermischt diese Namen mit dem Klassennamen: Wenn die Klasse Foo ein Attribut namens __a hat, kann sie nicht von Foo.__a aufgerufen werden. (Ein hartnäckiger Benutzer könnte immer noch Zugriff erhalten, indem er Foo._Foo__a aufruft.) Im Allgemeinen sollten doppelt führende Unterstriche nur verwendet werden, um Namenskonflikte mit Attributen in Klassen zu vermeiden, die zur Unterklasse gehören.

Hinweis: Es gibt einige Kontroversen über die Verwendung von __Namen (siehe unten).

10.5.10 Konstanten

Konstanten werden in der Regel auf Modulebene definiert und in Großbuchstaben mit unterstrichenen Trennwörtern geschrieben. Beispiele sind MAX_OVERFLOW und TOTAL.

Abschließend

Die restlichen Informationen aus PEP 8 werden in einem separatem Post beschrieben, da diese, meiner Meinung nach, einen eigenen Post verdient haben. Dort geht es hauptsächlich um generelle „Programmier-Empfehlungen“.

Wer die volle Version von PEP 8 in englischer Sprache lesen möchte, der kann direkt zu den Python PEPs es ist immer schön das Original zu lesen.


Zuletzt bearbeitet am 14.02.2019