Python 编码风格指南(收藏)

发布时间:2020-05-12编辑:脚本学堂
这是一篇有关python编程风格的指南性文章,介绍了一些规范的、良好的python编码风格,有需要的朋友参考下。
本节是 Python 编码风格指南 第二部分的内容,请大家继续阅读。
    同代码不一致的注释比没注释更差。当代码修改时,始终优先更新注释!
    注释应该是完整的句子。如果注释是一个短语或句子,首字母应该大写,除非它是一个以小写字母开头的标识符 (永远不要修改标识符的大小写)。
    如果注释很短,可以省略末尾的句号。注释块通常由一个或多个段落组成,段落是由完整的句子构成的,每个句子应该以句号结尾。
    你应该在结束语句的句点 (a sentence-ending period) 后使用两个空格。
   用英语书写时,断词和空格是可用的 (When writing English, Strunk and White  apply)。
    非英语国家的 Python 程序员:请用英语书写你的注释,除非你 120% 的确信代码永远不会被不懂你的语言的人阅读。

  注释块 (Block Comments)

    注释块通常应用于跟随其后的一些 (或者全部) 代码,并和这些代码有着相同的缩进层次。注释块中每行以 '#' 和一个空格开始 (除非它是注释内的缩进文本)。

    注释块内的段落以仅含单个 '#' 的行分割。

  行内注释 (Inline Comments)

    节俭使用行内注释。

    一个行内注释是和语句在同一行的注释。行内注释应该至少用两个空格和语句分开。
    它们应该以一个 '#' 和单个空格开始。

    行内注释不是必需的,事实上,如果说的是显而易见事,还会使人分心。不要这样做 :
    x = x + 1                 # Increment x
    但是有时,这样是有益的:
        x = x + 1                 # Compensate for border

文档字符串 (Documentation Strings)

    书写好的文档字符串 (又名"docstrings") 的约定,在 PEP 257 [3] 中是永存的。

    - 为所有公共模块、函数、类和方法书写文档字符串。文档字符串对非公开的方法不是必要的,但你应该有一条注释来描述这个方法做什么;这条注释应该出现在"def" 行之后。

    - PEP 257 描述了好的文档字符串约定。一定注意,多行文档字符串结尾的 """ 应该单独成行,并推荐在其前加一空行,例如:
      """Return a foobang
      Optional plotz says to frobnicate the bizbaz first.
      """
    - 对单行的文档字符串,结尾的 """ 在同一行也可以。

版本注记 (Version Bookkeeping)
    如果你必须把 Subversion、CVS、or RCS crud 包含在你的源文件中,按如下做:
   

复制代码 代码示例:
     __version__ = "$Revision: 54700 $"
        # $Source$

    这些行应该包含在模块的文档字符串之后,任何其他代码之前,上下各用一个空行分隔 。

命名约定 (Naming Conventions)

    Python 库的命名约定有点混乱,所以我们将永远不能使之变得完全一致。不过还是有普遍推荐的命名规范的。新的模块和包 (包括第三方的框架) 应该根据这些标准书写
    ,但对有不同风格的已有的库,保持内部的一致性是首选的。

  描述:命名风格 (Descriptive: Naming Styles)

    有许多不同的命名风格。以下的有助于辨认正在使用的命名风格,这独立于它们的作用。

    以下的命名风格是众所周知的:
   

- 单个小写字母 (b)
    - 单个大写字母 (B)
    - 小写串 (lowercase)
    - 带下划线的小写串 (lower_case_with_underscores)
    - 大写串 (UPPERCASE)
    - 带下划线的大写串 (UPPER_CASE_WITH_UNDERSCORES)
    - 首字母大写单词串 (CapitalizedWords) (或 CapWords、CamelCase -- 因其字母看起来错落有致,故得此名)。有时这也被称作 StudlyCaps。

      注意: 在 CapWords 中使用缩写,需要把缩写的所有字母大写。故HTTPServerError 比 HttpServerError 更好。
    - 混合大小写串 (mixedCase) (与首字母大写串不同之处在于第一个字符是小写的!)
    - 带下划线的首字母大写串 (Capitalized_Words_With_Underscores) (丑陋!)

    还有一种风格,使用特别的短前缀来将相关的名字分成组。这在 Python 中不常用,但是出于完整性要提一下。例如,os.stat() 函数返回一个 tuple,其元素传统上有象 st_mode, st_size, st_mtime 等等这样的名字。(这样做是为了强调与 POSIX 系统调用结构体的相关性,这有助于程序员熟悉那些相关性。)

    X11 库的所有公开函数以 X 开头。在 Python 中,这个风格通常认为是不必要的,因为属性和方法名以对象作前缀,而函数名以模块名作前缀。

    另外,以下用前导或后置下划线的特殊形式是被公认的 (通常这些可以和任何习惯相组合):

    - _single_leading_underscore:
      (单前导下划线): 弱的 "内部使用 (internal use)" 标志。
      例如,"from M import *" 不会导入以下划线开头的对象。

    - single_trailing_underscore_:
      (单后置下划线): 习惯上用于避免与 Python 关键词的冲突。
      例如:
      Tkinter.Toplevel(master, class_='ClassName')

    - __double_leading_underscore:
      (双前导下划线): 当用于命名 class 属性时,会触发名字重整 (name mangling)。
      (在类 FooBar 中,__boo 变成 _FooBar__boo;参加下面)。

    - __double_leading_and_trailing_underscore__:
      (双前导和后置下划线):存在于用户控制的 (user-controlled) 名字空间的"magic" 对象或属性。例如:
      __init__, __import__ or __file__
      决不要发明这样的名字,仅像文档中那样使用即可。

  说明:命名约定 (Prescriptive: Naming Conventions)

    避免采用的名字 (Names to Avoid)

      决不要用字符 'l' (小写字母 el),'O' (大写字母 oh),或 'I' (大写字母 eye)作为单个字符的变量名。

      在一些字体中,这些字符不能与数字 1 和 0 区别开。当想要使用 'l' 时,用'L'代替它。

    包和模块名 (Package and Module Names)

      模块名应该是简短的、全部小写的名字。可以在模块名中使用下划线以提高可读性。Python 包名也应该是简短的、全部小写的名字,尽管不推荐使用下划线。

      因为模块名被映射到文件名,有些文件系统大小写不敏感并且截短长名字,所以把 模块名选择为相当短就很重要了 -- 这在 Unix 上不是问题,但当把代码迁移到
      Mac、Windows 或 DOS 上时,就可能是个问题了。

      当一个用 C 或 C++ 写的扩展模块,有一个伴随的 Python 模块来提供一个更高层(例如,更面向对象) 的接口时,C/C++ 模块名有一个前导下划线 (如:_socket)。

    类名 (Class Names)

      几乎没有例外,类名使用首字母大写单词串 (CapWords) 的约定。
      内部使用的类使用一个额外的前导下划线。

    异常名 (Exception Names)

      因为异常应该是类,故类命名约定也适用于异常。然而,你应该对异常名添加后缀"Error" (如果该异常的确是一个错误)。

    全局变量名 (Global Variable Names)

      (让我们希望这些变量只打算用于一个模块内部。) 这些约定与那些用于函数的约定差不多。

      对设计为通过 "from M import *" 来使用的模块,应采用 __all__ 机制来防止导出全局变量;或者使用旧的约定,为该类全局变量加一个前导下划线 (可能你想表明这些全局变量是 "module non-public")。

    函数名 (Function Names)

      函数名应该为小写,必要时可用下划线分隔单词以增加可读性。

      混合大小写 (mixedCase) 仅被允许用于这种风格已经占优势的上下文 (如:threading.py),以便保持向后兼容。

    函数和方法的参数 (Function and method arguments)

      对实例的方法,总是用 'self' 做第一个参数。

      对类的方法,总是用 'cls' 做第一个参数。

      如果函数的参数名与保留关键字冲突,在参数名后加一个下划线,比用缩写、错误的拼写要好。因此 "print_" 比 "prnt" 好。(也许使用同义词来避免冲突更好。)

    方法名和实例变量 (Method Names and Instance Variables)

      采用函数命名规则:小写单词,必要时可用下划线分隔单词以增加可读性。

      仅对 non-public 方法和实例变量采用一个前导下划线。

      为避免与子类命名冲突,采用两个前导下划线来触发 Python 的命名重整规则。

      Python 用类名重整这些名字:如果类 Foo 有一个属性名为 __a, 它不能以Foo.__a 访问。(执著的用户还是可以通过 Foo._Foo__a 得到访问权。) 通常,双前导下划线仅被用来避免与基类的属性发生名字冲突。

      注:关于 __names 的作用存在一些争论 (见下面)。

    继承的设计 (Designing for inheritance)

      总是确定类的方法和实例变量 (统称为属性) 是否应该被公开或者不公开。如果有疑问,选择不公开;今后把其改为公开比把一个公开属性改为非公开要容易。

      公开属性是那些你期望你的类的不相关的客户使用,并根据你的承诺来避免向后不兼容变更。非公开属性是那些确定不给第三方使用的;你不保证非公开属性不变、甚至被移除。

      这里我们不使用术语 "private",因为在 Python 中没有属性是真正私有的 (没有通常的无用功 (unnecessary alinuxjishu/9952.html target=_blank class=infotextkey>mount of work))。

      另一类属性是 "subclass API" 的一部分 (在其他语言中通常称为 "protected")。
      一些类被设计为基类,要么被扩展,要么类的某些行为被修改。当设计这样的类时,注意明确决定哪些属性是公开的,哪些是子类 API 的一部分,及哪些是真正仅被你的基类使用。

      谨记这些 Python 特色的指导方针:

      - 公开属性应该没有前导下划线。

      - 如果公开属性名和保留关键字冲突,在你的属性名后添加一个后置下划线。这比缩写或者错误的拼写更可取。(然而,尽管这条规则,对任何已知是类的变量或者参数,尤其是类方法的第一个参数,'cls' 是首选拼写方式。)

        注1:参见上面对类方法的参数名的建议。

      - 对简单的公开数据属性 (data attribute),最好只暴露属性名,没有复杂的访问/修改方法 (accessor/mutator methods)。谨记 Python 为将来增强提供了一条容易的途径,你应该发现简单数据属性需要增加功能行为。在那种情况,用特性(properties) 把功能实现隐藏在简单数据属性访问语法后面。

        注1:特性仅工作于 new-style 的类。

        注2:尝试不管功能行为的副作用,尽管像 cache 之类副作用通常是好的。

        注3:避免对费时的计算操作使用特性;属性符号使调用者相信访问是 (相对)廉价的。