Python Enhancement Proposals

PEP 7 – Style Guide for C Code

PEP
7
Title
C 代码的风格指南
Author
Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>
Status
Active
Type
Process
Created
05-Jul-2001
Post-History


Contents

介绍

本文档给出了构成 Python 的 C 语言实现的 C 代码的编码规则。请参见描述 Python 代码风格指南的配套信息性 PEP 1

注意,规则是用来被打破的。打破某项规则的两个好理由:

  1. 当应用该规则会使代码的可读性降低,即使是对于习惯于阅读遵循规则的代码的人来说。
  2. 要与周围的代码保持一致,这些代码也会破坏它(也许是出于历史原因)– 尽管这也是一个清理别人的烂摊子的机会(真正的 XP 风格)。

C 方言

  • 3.6 之前的 Python 版本使用 ANSI/ISO 标准 C (1989 年版本的标准)。这意味着(除其他外)所有的声明都必须在块的顶部(不一定在函数的顶部)。
  • 大于或等于 3.6 的 Python 版本使用 C89 与几个精选的 C99 特性:
    • 标准整数类型在 <stdint.h><inttypes.h>。我们需要固定宽度的整数类型。
    • static inline 函数
    • 指定的初始化器(对类型声明来说特别好)
    • 混杂的声明
    • 布尔运算
    • C++ 风格的行注释

    未来的 C99 特性可能会被添加到这个列表中,这取决于编译器的支持(主要是明显的 MSVC)。

  • 不要使用 GCC 扩展(例如,不要写没有尾部反斜线的多行字符串)。
  • 所有的函数声明和定义必须使用完整的原型(即指定所有参数的类型)。
  • 只在 Python 3.6 或更高版本中使用 C++ 风格的 // 单行注释。
  • 在主要的编译器(gcc、VC++ 和其他一些)中没有编译器警告。

代码布局

  • 使用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 albatross; /* correct */
    return(albatross); /* incorrect */
    
  • 函数和宏的调用方式: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 */
    }
    
  • 在函数、结构定义和函数内部的主要部分周围放上空行。
  • 注释放在其描述的代码之前。
  • 所有的函数和全局变量都应该被声明为静态的,除非它们将成为已发布的接口的一部分
  • 对于外部函数和变量,我们总是在 “Include” 目录下的适当头文件中进行声明,该文件使用 PyAPI_FUNC() 宏,像这样
    PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);
    

命名公约

  • 对公共函数使用 Py 前缀;对静态函数绝不使用。Py_ 前缀保留给全局服务例程,如 Py_FatalError;特定的例程组(如特定的对象类型 API)使用更长的前缀,如 PyString_ 用于字符串函数。
  • 公共函数和变量使用带下划线的 MixedCase,像这样:PyObject_GetAttrPy_BuildValuePyExc_TypeError
  • 有时候,一个 “internal” 函数必须对加载器可见;我们使用 _Py 前缀来表示,例如:_PyObject_Dump
  • 宏应该有一个 MixedCase 前缀,然后使用大写字母,例如:PyString_AS_STRINGPy_PRINT_RAW

文档字符串

  • 使用 PyDoc_STR()PyDoc_STRVAR() 宏来处理文档字符串,以支持在没有文档字符串的情况下构建 Python (./configure --without-doc-strings)。

    对于需要支持高于 2.3 版本的 Python 的 C 语言代码,你可以在包括 Python.h 之后包括这个

    #ifndef PyDoc_STR
    #define PyDoc_VAR(name)         static char name[]
    #define PyDoc_STR(str)          (str)
    #define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
    #endif
    
  • 每个函数文档字符串的第一行应该是一个 “签名行”,给出参数和返回值的简要概述。比如说
    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 编译器会抱怨这一点。

参考

1
PEP 8,”Python代码的风格指南”,van Rossum, Warsaw(http://www.python.org/dev/peps/pep-0008

Source: https://github.com/python/peps/blob/master/pep-0007.txt

Last modified: 2017-11-11 19:28:55 GMT