PEP 7 – Style Guide for C Code
- Autor:
- Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>
- Status:
- Aktiv
- Typ:
- Prozess
- Erstellt:
- 05-Jul-2001
- Post-History:
Einleitung
Dieses Dokument gibt Kodierungsrichtlinien für den C-Code, aus dem die C-Implementierung von Python besteht. Bitte beachten Sie die begleitende Informations-PEP, die die Style-Richtlinien für Python-Code beschreibt.
Beachten Sie, dass Regeln dazu da sind, um sie zu brechen. Zwei gute Gründe, eine bestimmte Regel zu brechen:
- Wenn die Anwendung der Regel den Code weniger lesbar machen würde, selbst für jemanden, der es gewohnt ist, Code zu lesen, der den Regeln folgt.
- Um konsistent mit umgebendem Code zu sein, der sie ebenfalls bricht (vielleicht aus historischen Gründen) – obwohl dies auch eine Gelegenheit ist, das Durcheinander anderer aufzuräumen (im echten XP-Stil).
C-Standards
Befolgen Sie die folgenden Standards. Für Funktionen, die nicht im relevanten Standard enthalten sind, verwenden Sie CPython-spezifische Wrapper (z.B.: _Py_atomic_store_int32, Py_ALWAYS_INLINE, Py_ARITHMETIC_RIGHT_SHIFT; _Py_ALIGNED_DEF in öffentlichen Headern). Versuchen Sie beim Hinzufügen solcher Wrapper, sie leicht an nicht unterstützte Compiler anzupassen.
- Python 3.11 und neuere Versionen verwenden C11 ohne optionale Features. Die öffentliche C-API sollte mit C99 und C++ kompatibel sein.
(Als Erinnerung an alle Leser: Diese PEP ist ein *Styleguide*; diese Regeln sind dazu da, um sie zu brechen.)
- Python 3.6 bis 3.10 verwenden C89 mit mehreren ausgewählten C99-Features.
- Standard-Ganzzahltypen in
<stdint.h>und<inttypes.h>. Wir benötigen die Ganzzahltypen mit fester Breite. static inlineFunktionen- Designierte Initialisierer (besonders nützlich für Typdeklarationen)
- Vermischte Deklarationen
- Booleans
- C++-artige Zeilenkommentare
- Standard-Ganzzahltypen in
- Python-Versionen vor 3.6 verwendeten den ANSI/ISO-Standard C (die Version des Standards von 1989). Das bedeutete unter anderem, dass alle Deklarationen am Anfang eines Blocks standen.
Gängige C-Code-Konventionen
- Verwenden Sie keine Compiler-spezifischen Erweiterungen, wie die von GCC oder MSVC. Schreiben Sie zum Beispiel keine mehrzeiligen Strings ohne abschließende Backslashes.
- Alle Funktionsdeklarationen und -definitionen müssen vollständige Prototypen verwenden. Das heißt, geben Sie die Typen aller Argumente an und verwenden Sie
(void), um Funktionen ohne Argumente zu deklarieren. - Keine Compiler-Warnungen mit wichtigen Compilern (gcc, VC++, einige andere).
static inlineFunktionen sollten in neuem Code Makros vorgezogen werden.
Code-Layout
- Verwenden Sie 4 Leerzeichen für Einrückungen und überhaupt keine Tabs.
- Keine Zeile sollte länger als 79 Zeichen sein. Wenn Ihnen und der vorherigen Regel zusammen nicht genügend Platz zum Codieren bleibt, ist Ihr Code zu kompliziert – ziehen Sie die Verwendung von Unterroutinen in Betracht.
- Keine Zeile sollte mit einem Leerzeichen enden. Wenn Sie glauben, signifikante abschließende Leerzeichen zu benötigen, denken Sie noch einmal nach – der Editor von jemandem könnte sie routinemäßig löschen.
- Funktionsdefinitionsstil: Funktionsname in Spalte 1, äußerste geschweifte Klammern in Spalte 1, Leerzeile nach lokalen Variablendeklarationen.
static int extra_ivars(PyTypeObject *type, PyTypeObject *base) { int t_size = PyType_BASICSIZE(type); int b_size = PyType_BASICSIZE(base); assert(t_size >= b_size); /* type smaller than base! */ ... return 1; }
- Code-Struktur: ein Leerzeichen zwischen Schlüsselwörtern wie
if,forund der folgenden linken Klammer; keine Leerzeichen innerhalb der Klammern; Klammern sind überall erforderlich, auch dort, wo C sie weglassen erlaubt, aber fügen Sie sie nicht zu Code hinzu, den Sie nicht anderweitig ändern. Neuer C-Code erfordert immer Klammern. Klammern sollten wie gezeigt formatiert werden.if (mro != NULL) { ... } else { ... }
- Die Return-Anweisung sollte *keine* redundanten Klammern bekommen.
return(albatross); /* incorrect */
Stattdessen
return albatross; /* correct */
- Stil von Funktions- und Makroaufrufen:
foo(a, b, c)– kein Leerzeichen vor der öffnenden Klammer, keine Leerzeichen innerhalb der Klammern, keine Leerzeichen vor Kommas, ein Leerzeichen nach jedem Komma. - Setzen Sie immer Leerzeichen um Zuweisungs-, boolesche und Vergleichsoperatoren. In Ausdrücken mit vielen Operatoren fügen Sie Leerzeichen um die äußersten (niedrig priorisierten) Operatoren hinzu.
- Zeilenumbrüche bei langen Zeilen: Wenn möglich, brechen Sie nach Kommas in der äußersten Argumentliste ab. Richten Sie Fortsetzungszeilen immer entsprechend ein, z. B.
PyErr_Format(PyExc_TypeError, "cannot create '%.100s' instances", type->tp_name);
- Wenn Sie einen langen Ausdruck an einem binären Operator abbrechen, sollten die Klammern wie gezeigt formatiert werden.
if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && type->tp_dictoffset == b_size && (size_t)t_size == b_size + sizeof(PyObject *)) { return 0; /* "Forgive" adding a __dict__ only */ }
Es ist in Ordnung, Operatoren am Ende von Zeilen zu platzieren, insbesondere um konsistent mit umgebendem Code zu sein. (Siehe PEP 8 für eine längere Diskussion.)
- Richten Sie Zeilenfortsetzungszeichen in mehrzeiligen Makros vertikal aus.
- Makros, die als Anweisung verwendet werden sollen, sollten das
do { ... } while (0)Makro-Idiom verwenden, ohne abschließendes Semikolon. Beispiel:#define ADD_INT_MACRO(MOD, INT) \ do { \ if (PyModule_AddIntConstant((MOD), (#INT), (INT)) < 0) { \ goto error; \ } \ } while (0) // To be used like a statement with a semicolon: ADD_INT_MACRO(m, SOME_CONSTANT);
- Heben Sie dateilokale Makros nach Gebrauch mit
#undefauf. - Setzen Sie Leerzeilen um Funktionen, Strukturdefinitionen und Hauptabschnitte innerhalb von Funktionen.
- Kommentare stehen vor dem Code, den sie beschreiben.
- Alle Funktionen und globalen Variablen sollten static deklariert werden, es sei denn, sie sollen Teil einer veröffentlichten Schnittstelle sein.
- Für externe Funktionen und Variablen haben wir immer eine Deklaration in einer geeigneten Header-Datei im Verzeichnis "Include", die das Makro
PyAPI_FUNC()und das MakroPyAPI_DATA()verwendet, wie folgt:PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *); PyAPI_DATA(PyTypeObject) PySuper_Type;
Namenskonventionen
- Verwenden Sie ein
Py-Präfix für öffentliche Funktionen; niemals für statische Funktionen. DasPy_-Präfix ist für globale Service-Routinen wiePy_FatalErrorreserviert; spezifische Funktionsgruppen (z.B. spezifische Objekt-Typ-APIs) verwenden ein längeres Präfix, z.B.PyString_für String-Funktionen. - Öffentliche Funktionen und Variablen verwenden MixedCase mit Unterstrichen, wie hier:
PyObject_GetAttr,Py_BuildValue,PyExc_TypeError. - Gelegentlich muss eine "interne" Funktion für den Loader sichtbar sein; wir verwenden dafür das Präfix
_Py, z.B.:_PyObject_Dump. - Makros sollten ein MixedCase-Präfix haben und dann Großbuchstaben verwenden, zum Beispiel:
PyString_AS_STRING,Py_PRINT_RAW. - Makroparameter sollten den
ALL_CAPS-Stil verwenden, damit sie leicht von C-Variablen und Strukturmitgliedern zu unterscheiden sind.
Dokumentations-Strings
- Verwenden Sie das Makro
PyDoc_STR()oderPyDoc_STRVAR()für Docstrings, um das Erstellen von Python ohne Docstrings zu unterstützen (./configure --without-doc-strings). - Die erste Zeile jedes Funktions-Docstrings sollte eine "Signaturzeile" sein, die eine kurze Zusammenfassung der Argumente und des Rückgabewerts liefert. Zum Beispiel:
PyDoc_STRVAR(myfunction__doc__, "myfunction(name, value) -> bool\n\n\ Determine whether name and value make a valid pair.");
Fügen Sie immer eine Leerzeile zwischen der Signaturzeile und dem Beschreibungstext ein.
Wenn der Rückgabewert der Funktion immer
Noneist (da es keinen sinnvollen Rückgabewert gibt), lassen Sie die Angabe des Rückgabetyps weg. - Beim Schreiben von mehrzeiligen Docstrings stellen Sie sicher, dass Sie immer Backslash-Fortsetzungen verwenden, wie im obigen Beispiel, oder String-Literal-Verkettung.
PyDoc_STRVAR(myfunction__doc__, "myfunction(name, value) -> bool\n\n" "Determine whether name and value make a valid pair.");
Obwohl einige C-Compiler String-Literale ohne beides akzeptieren,
/* BAD -- don't do this! */ PyDoc_STRVAR(myfunction__doc__, "myfunction(name, value) -> bool\n\n Determine whether name and value make a valid pair.");
nicht alle tun dies; der MSVC-Compiler wird dafür bekanntlich kritisiert.
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0007.rst
Zuletzt geändert: 2025-08-27 10:48:57 GMT