注释块 (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 包含在你的源文件中,按如下做:
这些行应该包含在模块的文档字符串之后,任何其他代码之前,上下各用一个空行分隔 。
命名约定 (Naming Conventions)
Python 库的命名约定有点混乱,所以我们将永远不能使之变得完全一致。不过还是有普遍推荐的命名规范的。新的模块和包 (包括第三方的框架) 应该根据这些标准书写
,但对有不同风格的已有的库,保持内部的一致性是首选的。
描述:命名风格 (Descriptive: Naming Styles)
有许多不同的命名风格。以下的有助于辨认正在使用的命名风格,这独立于它们的作用。
以下的命名风格是众所周知的:
注意: 在 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:避免对费时的计算操作使用特性;属性符号使调用者相信访问是 (相对)廉价的。