Numpy C样式指南

numpy c编码约定基于guido van rossum的python pep-0007,并增加了一些限制。有许多C编码约定,必须强调的是,numpy约定的主要目标不是选择“最好的”,关于这一点,肯定会有分歧,但要实现一致性。因为numpy约定与pep-0007中的约定非常接近,所以pep用作下面的模板,在适当的位置添加numpy和变化。

NUMPY修改后的PEP-0007

介绍

本文给出了包含numpy的C实现的C代码的编码约定。注意,规则是要打破的。打破特定规则的两个好理由:

  1. 当应用该规则时,即使对于习惯于读取遵循规则的代码的人,代码的可读性也会降低。
  2. 为了与破坏它的周围代码保持一致(可能是出于历史原因),尽管这也是一个清理别人混乱的机会。

C方言

  • 使用ANSI/ISO标准C(1989版标准)。这意味着,除其他许多事情外,所有声明都必须在块的顶部(不一定在函数的顶部)。

  • 不要使用gcc扩展(例如,不要写没有尾随反斜杠的多行字符串)。最好将长字符串拆分成单独的行,如:

    "blah blah"
    "blah blah"
    

    这将与MSVC一起工作,否则它会在很长的字符串上阻塞。

  • 所有函数声明和定义都必须使用完整的原型(即指定所有参数的类型)。

  • 不要使用C++风格/一行注释,它们是不可移植的。注意:这将随着向C++的建议过渡而改变。

  • 对于主要编译器(gcc、vc++和其他一些编译器),没有编译器警告。注意:numpy仍然会生成需要处理的编译器警告。

代码布局

  • 使用4个空格缩进,完全不使用制表符。

  • 行不能超过80个字符。如果这条规则和前面的规则不能给您足够的空间来进行编码,那么您的代码就太复杂了,请考虑使用子例程。

  • 任何行都不应以空白结尾。如果您认为您需要大量的尾随空格,请再考虑一次,某个编辑器可能会将其作为例行程序删除。

  • 函数定义样式:列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;
    }
    

    如果过渡到C++,那么这个表单可能会被放松,因此,要内联的短类方法可以在与函数名相同的行上返回类型。然而,这还没有确定。

  • 代码结构:关键字之间的一个空格,如 iffor 以及下面的左括号;括号内没有空格;全部用大括号括起来 if 分支,并且没有语句与 if . 它们的格式应如下所示:

    if (mro != NULL) {
        one_line_statement;
    }
    else {
        ...
    }
    
    
    for (i = 0; i < n; i++) {
        one_line_statement;
    }
    
    
    while (isstuff) {
        dostuff;
    }
    
    
    do {
        stuff;
    } while (isstuff);
    
    
    switch (kind) {
        /* Boolean kind */
        case 'b':
            return 0;
        /* Unsigned int kind */
        case 'u':
            ...
        /* Anything else */
        default:
            return 3;
    }
    
  • 返回语句应该 not 获取多余的括号::

    return Py_None; /* correct */
    return(Py_None); /* incorrect */
    
  • 函数和宏调用样式: foo(a, b, c) 开括号前没有空格,括号内没有空格,逗号前没有空格,每个逗号后有一个空格。

  • 始终在赋值、布尔和比较运算符周围放置空格。在使用大量运算符的表达式中,在最外层(最低优先级)运算符周围添加空格。

  • 断开长行:如果可以,请在最外面的参数列表中的逗号后断开。始终适当地缩进接续行,例如::

    PyErr_SetString(PyExc_TypeError,
            "Oh dear, you messed up.");
    

    这里适当地表示至少两个标签。没有必要用函数调用的左括号将所有内容排成一行。

  • 在二元运算符处中断一个长表达式时,该运算符位于前一行的末尾,例如::

    if (type > tp_dictoffset != 0 &&
            base > tp_dictoffset == 0 &&
            type > tp_dictoffset == b_size &&
            (size_t)t_size == b_size + sizeof(PyObject *)) {
        return 0;
    }
    

    注意,多行布尔表达式中的术语是缩进的,以便使代码块的开头清晰可见。

  • 在函数、结构定义和函数内部的主要部分周围放置空行。

  • 注释位于它们描述的代码之前。多行注释应如下所示:

    /*
     * This would be a long
     * explanatory comment.
     */
    

    尾随注释应谨慎使用。而不是::

    if (yes) {/* Success! */
    

    DO:

    if (yes) {
        /* Success! */
    
  • 所有函数和全局变量在当前编译单元之外不需要时都应声明为静态的。

  • 在头文件中声明外部函数和变量。

命名约定

  • numpy公共函数没有一致的前缀,但它们都以某种前缀开头,后跟下划线,在camel中是这样的: PyArray_DescrAlignConverterNpyIter_GetIterNext . 以后的名字应该是这样的 Npy*_PublicFunction 如果星星是合适的。
  • 公共宏应该具有 NPY_ 前缀,然后使用大写,例如, NPY_DOUBLE .
  • 私有函数应为小写,并带有下划线,例如: array_real_get . 不应使用单前导下划线,但由于历史事故,某些当前函数名违反了该规则。这些函数在某些时候应该被重命名。

功能文档

目前,numpy没有C函数文档标准,但需要一个。大多数numpy函数没有记录在代码中,这应该会改变。一种可能是带有插件的doxygen,这样用于Python函数的numpy样式也可以用于记录C函数,请参见doc/c doc/中的文件。