Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 7 – C 代码风格指南

作者:
Guido van Rossum <guido at python.org>,Barry Warsaw <barry at python.org>
状态:
活跃
类型:
流程
创建:
2001年7月5日
修订历史:


目录

引言

本文档提供了 Python C 实现的 C 代码的编码约定。请参阅配套的信息性 PEP,其中描述了Python 代码的风格指南

注意,规则是为了被打破而存在的。打破特定规则的两个充分理由是

  1. 当应用规则会使代码可读性降低时,即使对于习惯阅读遵循规则的代码的人也是如此。
  2. 为了与周围也违反该规则的代码保持一致(可能是出于历史原因)——尽管这也是清理他人代码混乱的机会(以真正的 XP 风格)。

C 方言

  • Python 3.11 及更高版本使用 C11,不使用可选特性。公共 C API 应与 C++ 兼容。
  • Python 3.6 到 3.10 使用 C89,并包含一些选定的 C99 特性
    • <stdint.h><inttypes.h> 中使用标准整数类型。我们需要固定宽度的整数类型。
    • static inline 函数
    • 指定初始化器(对于类型声明尤其有用)
    • 混合声明
    • 布尔值
    • C++ 风格的行注释
  • 3.6 之前的 Python 版本使用 ANSI/ISO 标准 C(1989 年版本的标准)。这意味着(除其他事项外)所有声明必须位于代码块的顶部(不一定是函数的顶部)。
  • 不要使用编译器特定的扩展,例如 GCC 或 MSVC 的扩展(例如,不要在没有尾部反斜杠的情况下编写多行字符串)。
  • 所有函数声明和定义都必须使用完整的原型(即指定所有参数的类型)。
  • 主要编译器(gcc、VC++、其他一些编译器)没有编译器警告。
  • 在新的代码中,应优先使用 static inline 函数而不是宏。

代码布局

  • 使用 4 个空格缩进,完全不使用制表符。
  • 每行长度不应超过 79 个字符。如果此规则和上一条规则加在一起没有给你足够的编码空间,那么你的代码过于复杂——考虑使用子程序。
  • 任何一行都不应该以空格结尾。如果你认为需要重要的尾随空格,请再三考虑——某些人的编辑器可能会将其作为例行公事删除。
  • 函数定义风格:函数名位于第 1 列,最外层花括号位于第 1 列,局部变量声明后有空行。
    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;
    }
    
  • 代码结构:在 iffor 等关键字和后面的左括号之间留一个空格;括号内没有空格;在所有地方都需要花括号,即使在 C 允许省略它们的地方,但不要将其添加到你没有修改的其他代码中。所有新的 C 代码都需要花括号。花括号应按如下所示格式化
    if (mro != NULL) {
        ...
    }
    else {
        ...
    }
    
  • return 语句不应包含冗余括号
    return(albatross); /* incorrect */
    

    改为

    return albatross; /* correct */
    
  • 函数和宏调用风格:foo(a, b, c)——左括号前没有空格,括号内没有空格,逗号前没有空格,每个逗号后有一个空格。
  • 始终在赋值、布尔和比较运算符周围添加空格。在使用大量运算符的表达式中,在最外层(最低优先级)运算符周围添加空格。
  • 换行:如果可以,在最外层参数列表中的逗号后换行。始终适当地缩进续行,例如
    PyErr_Format(PyExc_TypeError,
                 "cannot create '%.100s' instances",
                 type->tp_name);
    
  • 当你在二元运算符处换行时,花括号应按如下所示格式化
    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 */
    }
    

    将运算符放在行尾是可以的,特别是为了与周围的代码保持一致。(有关更详细的讨论,请参阅PEP 8。)

  • 在多行宏中垂直对齐续行字符。
  • 旨在用作语句的宏应使用 do { ... } while (0) 宏习语,不带最终分号。示例
    #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);
    
  • 在使用后 #undef 文件局部宏。
  • 在函数、结构定义以及函数内部的主要部分周围放置空行。
  • 注释放在它们描述的代码之前。
  • 所有函数和全局变量都应声明为静态,除非它们是要成为发布接口的一部分。
  • 对于外部函数和变量,我们始终在“Include”目录中的相应头文件中有一个声明,该声明使用 PyAPI_FUNC() 宏和 PyAPI_DATA() 宏,如下所示
    PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);
    
    PyAPI_DATA(PyTypeObject) PySuper_Type;
    

命名约定

  • 对于公共函数使用 Py 前缀;对于静态函数则从不使用。 Py_ 前缀保留用于全局服务例程,例如 Py_FatalError;特定组的例程(例如,特定对象类型的 API)使用更长的前缀,例如字符串函数的 PyString_
  • 公共函数和变量使用混合大小写并带下划线,例如:PyObject_GetAttrPy_BuildValuePyExc_TypeError
  • 有时“内部”函数必须对加载器可见;我们为此使用 _Py 前缀,例如:_PyObject_Dump
  • 宏应具有混合大小写前缀,然后使用大写,例如:PyString_AS_STRINGPy_PRINT_RAW
  • 宏参数应使用 ALL_CAPS 样式,以便于将其与 C 变量和结构成员区分开来。

文档字符串

  • 对于文档字符串,使用 PyDoc_STR()PyDoc_STRVAR() 宏,以支持在没有文档字符串的情况下构建 Python(./configure --without-doc-strings)。
  • 每个函数文档字符串的第一行应为“签名行”,简要概述参数和返回值。例如
    PyDoc_STRVAR(myfunction__doc__,
    "myfunction(name, value) -> bool\n\n\
    Determine whether name and value make a valid pair.");
    

    始终在签名行和描述文本之间包含一个空行。

    如果函数的返回值始终为 None(因为没有有意义的返回值),则不包含返回值类型的指示。

  • 编写多行文档字符串时,请务必始终使用反斜杠续行,如上例所示,或使用字符串文字连接
    PyDoc_STRVAR(myfunction__doc__,
    "myfunction(name, value) -> bool\n\n"
    "Determine whether name and value make a valid pair.");
    

    尽管一些 C 编译器接受没有两者之一的字符串文字

    /* BAD -- don't do this! */
    PyDoc_STRVAR(myfunction__doc__,
    "myfunction(name, value) -> bool\n\n
    Determine whether name and value make a valid pair.");
    

    但并非所有编译器都这样做;已知 MSVC 编译器会对此提出抱怨。


来源:https://github.com/python/peps/blob/main/peps/pep-0007.rst

上次修改时间:2024年9月9日14:02:27 GMT