Python风格规范

Posted ZH奶酪(张贺)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python风格规范相关的知识,希望对你有一定的参考价值。

原文:https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/#comments

分号

  • 不要在行尾加分号, 也不要用分号将两条命令放在同一行.

行长度

  • 每行不超过80个字符
  • 不要使用反斜杠连接行.
  • Python会将 圆括号, 中括号和花括号中的行隐式的连接起来 , 你可以利用这个特点. 如果需要, 你可以在表达式外围增加一对额外的圆括号.

缩紧

  • 绝对不要用tab, 也不要tab和空格混用.
  • 对于行连接的情况, 你应该要么垂直对齐换行的元素(见 行长度 部分的示例), 或者使用4空格的悬挂式缩进(这时第一行不应该有参数):

空格

  • 不要用空格来垂直对齐多行间的标记, 因为这会成为维护的负担(适用于:, #, =等):

Shebang

  • 大部分.py文件不必以#!作为文件的开始. 根据 PEP-394 , 程序的main文件应该以 #!/usr/bin/python2或者 #!/usr/bin/python3开始.
  • !先用于帮助内核找到Python解释器, 但是在导入模块时, 将会被忽略. 因此只有被直接执行的文件中才有必要加入#!.

注释

  • 文档字符串
    • 这些字符串可以通过对象的__doc__成员被自动提取, 并且被pydoc所用. (你可以在你的模块上运行pydoc试一把, 看看它长什么样).
    • 文档字符串的惯例是使用三重双引号”“”( PEP-257 ).
    • 首先是一行以句号, 问号或惊叹号结尾的概述(或者该文档字符串单纯只有一行).
    • 接着是一个空行.
    • 接着是文档字符串剩下的部分, 它应该与文档字符串的第一行的第一个引号对齐.
  • 函数和方法
    • 一个函数必须要有文档字符串, 除非它满足以下条件: 外部不可见 / 非常短小 / 简单明了
    • 文档字符串应该包含函数做什么, 以及输入和输出的详细描述.
    • 通常, 不应该描述”怎么做”, 除非是一些复杂的算法.
    • 文档字符串应该提供足够的信息, 当别人编写代码调用该函数时, 他不需要看一行代码, 只要看文档字符串就可以了.
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."""
  • 块注释和行注释
    • 对于复杂的操作, 应该在其操作开始前写上若干行注释.
    • 对于不是一目了然的代码, 应在其行尾添加注释.
    • 绝不要描述代码. 假设阅读代码的人比你更懂Python, 他只是不知道你的代码要做什么.

  • 如果一个类不继承自其它类, 就显式的从object继承. 嵌套类也一样.
  • 继承自 object 是为了使属性(properties)正常工作, 并且这样可以保护你的代码, 使其不受 PEP-3000 的一个特殊的潜在不兼容性影响. 这样做也定义了一些特殊的方法, 这些方法实现了对象的默认语义, 包括 new, init, delattr, getattribute, setattr, hash, repr, str
Yes: class SampleClass(object):
         pass


     class OuterClass(object):

         class InnerClass(object):
             pass


     class ChildClass(ParentClass):
         """Explicitly inherits from another class already."""

字符串

  • 即使参数都是字符串, 使用%操作符或者格式化方法格式化字符串. 不过也不能一概而论, 你需要在+和%之间好好判定.
Yes: 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)

No: x = \'%s%s\' % (a, b)  # use + in this case
    x = \'{}{}\'.format(a, b)  # use + in this case
    x = imperative + \', \' + expletive + \'!\'
    x = \'name: \' + name + \'; score: \' + str(n)
  • 避免在循环中用+和+=操作符来累加字符串. 由于字符串是不可变的, 这样做会创建不必要的临时对象, 并且导致二次方而不是线性的运行时间. 作为替代方案, 你可以将每个子串加入列表, 然后在循环结束后用 .join 连接列表.

导入格式

  • 每个导入应该独占一行
  • 导入总应该放在文件顶部, 位于模块注释和文档字符串之后, 模块全局变量和常量之前.
  • 导入应该按照从最通用到最不通用的顺序分组: 标准库导入 / 第三方库导入 / 应用程序指定导入
  • 每种分组中, 应该根据每个模块的完整包路径按字典序排序, 忽略大小写.

语句

  • 通常每个语句应该独占一行
  • 如果是if语句, 只有在没有else时也可以独占一行.

访问控制

  • 在Python中, 对于琐碎又不太重要的访问函数, 你应该直接使用公有变量来取代它们, 这样可以避免额外的函数调用开销. 当添加更多功能时, 你可以用属性(property)来保持语法的一致性.
  • 另一方面, 如果访问更复杂, 或者变量的访问开销很显著, 那么你应该使用像 get_foo() 和 set_foo() 这样的函数调用.

命名

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

Main

  • 即使是一个打算被用作脚本的文件, 也应该是可导入的. 并且简单的导入不应该导致这个脚本的主功能(main functionality)被执行, 这是一种副作用. 主功能应该放在一个main()函数中.
  • 在Python中, pydoc以及单元测试要求模块必须是可导入的. 你的代码应该在执行主程序前总是检查 if name == \'main\' , 这样当模块被导入时主程序就不会被执行.
  • 所有的顶级代码在模块导入时都会被执行. 要小心不要去调用函数, 创建对象, 或者执行那些不应该在使用pydoc时执行的操作.

以上是关于Python风格规范的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Pylint 来规范 Python 代码风格

代码风格.Python-整体风格.0002.让你Python程序软件目录更规范化?

text Python代码风格规范

Python规范:代码规范要注意

Python代码规范

分析一套源代码的代码规范和风格并讨论如何改进优化代码