不被注意的Python代码规范(1)---风格规范

Author Avatar
Trace 11月 14, 2017
  • 在其它设备中阅读本文章

最近已经在找工作了,发现各个公司对代码能力要求还是比较高的,谁叫咱还是要干码农的活呢,所以决心改一改自己的代码习惯,写出漂亮的代码。虽说重要的是实现功能,但是代码看起来漂亮,也会让人更舒服吧。下面会记录一些自己以前不太注意到的地方,主要准则还是“有则改之,无则加勉”。主要分成风格规范和语言规范两类。这篇是讲风格规范。

主要的参考是Google Python Style Guide

最长行

最大行长度不超过80个字符,很长的导入语句或者注释里的URL除外。
如果一个文本串的长度超过了80,可以以括号的形式来隐性连接两段短文本,如下:

x = ('This will build a very long long long long long '
    'long long long long long long string')

缩进

4个空格 作为缩进符
当字符数大于80了,可以有两种缩进方式选择,一种是超过80的部分,以固定缩进长度表示;第二种是以4个空格作为缩进,但是这种情况下,第一行就不能有任何内容,具体例子如下:

# 固定缩进长度
foo = long_function_name(var_one, var_two,
                var_three, var_four)
# 在字典中固定缩进长度
foo = {
    long_dictionary_key: value1 + 
                value2,
    ...
}

# 4个空格缩进,第一行没有任何东西
foo = long_function_name(
    var_one, var_two, var_three,
    var_four)
# 在字典中以4个空格缩进
foo = {
    long_dictionary_key:
        value1 + value2,
    ...
}

空行

高级定义(函数或者类)之间空两行,方法定义之间,以及class定义行和第一个方法定义行之间空一行。

空格

根据印刷标准的要求,来使用标点周围的空格。
当’=’出现在表示关键值或者默认参数值时,周围不需要加空格,如下:

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

注释

对于函数、方法的注释,应该使用文档字符串,当然假如函数非常短小,简单明了,就不必要注释了。下面会有具体的例子。

文档字符串是包、模块、类或函数里的第一个语句。这些字符串可以通过对象的__doc__成员被自动提取,并且被pydoc所用。(你可以在你的模块上运行pydoc试一把, 看看它长什么样)。我们对文档字符串的惯例是使用三重双引号”””( PEP-257 )。一个文档字符串应该这样组织:首先是一行以句号,问号或惊叹号结尾的概述(或者该文档字符串单纯只有一行)。接着是一个空行。接着是文档字符串剩下的部分,它应该与文档字符串的第一行的第一个引号对齐。

具体的文档字符串应该包括:

  • Args: 列出所有参数名字,并对参数进行描述
  • Returns: 描述返回值的类型和语义
  • Raises: 列出与接口有关的所有异常
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
    """Fetches rows from a Bigtable.

    Retrieves rows pertaining to the given keys from the Table instance
    represented by big_table.  Silly things may happen if
    other_silly_variable is not None.

    Args:
        big_table: An open Bigtable Table instance.
        keys: A sequence of strings representing the key of each table row
            to fetch.
        other_silly_variable: Another optional variable, that has a much
            longer name than the other args, and which does nothing.

    Returns:
        A dict mapping keys to the corresponding table row data
        fetched. Each row is represented as a tuple of strings. For
        example:

        {'Serak': ('Rigel VII', 'Preparer'),
         'Zim': ('Irk', 'Invader'),
         'Lrrr': ('Omicron Persei 8', 'Emperor')}

        If a key from the keys argument is missing from the dictionary,
        then that row was not found in the table.

    Raises:
        IOError: An error occurred accessing the bigtable.Table object.
    """
    pass

对于类的注释,也应该有一个用于描述该类的文档字符串。而且如果你的类有公共属性(Attributes),那么文档中应该有一个属性(Attributes)段。并且应该遵守和函数参数相同的格式。具体例子如下:

class SampleClass(object):
    """Summary of class here.

    Longer class information....
    Longer class information....

    Attributes:
        likes_spam: A boolean indicating if we like SPAM or not.
        eggs: An integer count of the eggs we have laid.
    """

    def __init__(self, likes_spam=False):
        """Inits SampleClass with blah."""
        self.likes_spam = likes_spam
        self.eggs = 0

    def public_method(self):
        """Performs operation blah."""

字符串

即使在参数都是字符串的情况下,也应该使用format或者%方法来格式化字符串。但是还是要在+format(或者%)判断性的选择。从下面的例子中,是不是说,假如只是两个字符串组合,就直接使用+,而假如是字符串潜入到别的内容中,就最好使用format或者%

x = a + b
x = '%s, %s!' % (imperative, expletive)
x = '{}, {}!'.format(imperative, expletive)
x = 'name: %s; score: %d' % (name, n)
x = 'name: {}; score: {}'.format(name, n)

在循环里不要使用+或者+=的形式来累加字符串。尽管字符串是不变的,但是这样会生成很多不必要的临时对象和结果,进而会造成运行时间平方次的增长,而不是线性增长。因此把自字符串先加到一个list里,然后在循环结束后join起来是更好的选择。

items = ['<table>']
for last_name, first_name in employee_list:
    items.append('<tr><td>%s, %s</td></tr>' % (last_name, first_name))
items.append('</table>')
employee_table = ''.join(items)

其他小规范:在同一个文件中使用统一的字符串引号;使用"""来表示多行字符串。

文件

在使用完文件之后,要关闭文件,推荐使用with的方式打开文件,因为这样会自动关闭文件。

with open("hello.txt") as hello_file:
    for line in hello_file:
        print line

导入格式

每一行只导入一个模块,模块导入顺序如下:

  1. 标准库导入
  2. 第三方库导入
  3. 程序指定导入

在同一个组中,又要按字母顺序导入,且忽略大小写

import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

命名

命名约定:

  • 所谓”内部(Internal)”表示仅模块内可用,或者在类内是保护或私有的。
  • 用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含。
  • 用双下划线(__)开头的实例变量或方法表示类内私有。
  • 将相关的类和顶级函数放在同一个模块里。不像Java,没必要限制一个类一个模块。
  • 对类名使用大写字母开头的单词(如CapWords,即Pascal风格),但是模块名应该用小写加下划线的方式(如lower_with_under.py).。尽管已经有很多现存的模块使用类似于CapWords.py这样的命名,但现在已经不鼓励这样做,因为如果模块名碰巧和类名一致,这会让人困扰。

下面是具体例子

Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under

正文到此结束,确实学到了很多代码规范,虽然写了2年多Python了,但是某些细节上的东西并没有注意太多。当然,正如参考文章最后提到的保持一致才是最终的目的,也就是与已有的代码风格保持一致,也许有些地方并不完全遵照上文里的规范,但是为了风格一致性,可以少许放弃规范,可以实现更好的代码沟通。


本文标题: 不被注意的Python代码规范(1)---风格规范
原始链接: https://oyeblog.com/2017/python_code_rules_1/
发布时间: 2017年11月14日 - 19时11分
最后更新: 2023年10月22日 - 15时06分
版权声明: 本站文章均采用CC BY-NC-SA 4.0协议进行许可。转载请注明出处!