Python 库的命名约定有点混乱,所以我们永远不会完全一致——不过,这里是当前推荐的命名标准。 新的模块和包(包括第三方框架)应该按照这些标准编写,但如果现有库具有不同的风格,则首选内部一致性。
优先原则
作为 API 公共部分对用户可见的名称应遵循反映用法而不是实现的约定。
描述性:命名样式
有很多不同的命名风格。 它有助于能够识别正在使用的命名风格,独立于它们的用途。
通常区分以下命名样式:
b(单个小写字母)
B(单个大写字母)
lowercase
lower_case_with_underscores
UPPERCASE
UPPER_CASE_WITH_UNDERSCORES
CapitalizedWords(或 CapWords 或 CamelCase —— 因其字母的凹凸不平而得名 [4])。 这有时也称为 StudlyCaps。
注意:在 CapWords 中使用首字母缩略词时,将首字母缩略词的所有字母大写。 因此 HTTPServerError 优于 HttpServerError。
Capitalized_Words_With_Underscores(与 CapitalizedWords 的不同之处在于首字母小写!)
还有一种使用简短的唯一前缀将相关名称组合在一起的风格。 这在 Python 中用得不多,但为了完整性而提及。 例如, os.stat() 函数返回一个元组,其项目传统上具有诸如 st_mode、st_size、st_mtime 等名称。 (这样做是为了强调与 POSIX 系统调用结构体的字段的对应关系,这有助于程序员熟悉。)
X11 库的所有公共函数都使用前导 X。 在 Python 中,这种风格通常被认为是不必要的,因为属性和方法名称以对象为前缀,而函数名称以模块名称为前缀。
此外,可以识别以下使用前导或尾随下划线的特殊形式(这些通常可以与任何大小写约定结合使用):
_single_leading_underscore: 弱“内部使用”指标。 例如。 from M import * 不导入名称以下划线开头的对象。
single_trailing_underscore_: 按照惯例使用以避免与 Python 关键字发生冲突,例如
tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore:命名类属性时,调用名称修改(在类 FooBar 中,__boo 变为 _FooBar__boo;见下文)。
__double_leading_and_trailing_underscore__: 存在于用户控制的命名空间中的“magic对象或属性。 E.g. __init__, __import__ or __file__. 永远不要发明这样的名字; 仅按照文档使用它们。
规定:命名约定
要避免的名字
切勿将字符“l”(小写字母 el)、“O”(大写字母 oh)或“I”(大写字母 eye)用作单个字符变量名。
在某些字体中,这些字符与数字一和零无法区分。 当想使用“l”时,请改用“L”。
ASCII 兼容性
标准库中使用的标识符必须与 ASCII 兼容,如 PEP 3131 的策略部分所述。
包和模块名称
模块应该有简短的全小写名称。 如果可以提高可读性,可以在模块名称中使用下划线。 尽管不鼓励使用下划线,但 Python 包也应该具有简短的全小写名称。
当用 C 或 C++ 编写的扩展模块附带提供更高级别(例如,更面向对象)接口的 Python 模块时,C/C++ 模块具有前导下划线(例如 _socket)。
类名
类名通常应使用 CapWords 约定。
在接口被记录并主要用作可调用的情况下,可以使用函数的命名约定。
请注意,内置名称有一个单独的约定:大多数内置名称是单个单词(或两个单词一起运行),CapWords 约定仅用于异常名称和内置常量。
类型变量名
PEP 484 中引入的类型变量的名称通常应使用 CapWords 首选短名称:T、AnyStr、Num。 建议在用于声明协变或逆变行为的变量中相应添加后缀_co或_contra:
from typing import TypeVar
VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)
异常名称
因为异常应该是类,类命名约定在这里适用。 但是,您应该在异常名称上使用后缀“Error”(如果异常实际上是错误)。
全局变量名
(让我们希望这些变量仅用于在一个模块内使用。)这些约定与函数的约定大致相同。
设计为通过 from M import * 使用的模块应该使用 __all__ 机制来防止导出全局变量,或者使用旧的约定,在此类全局变量前面加上下划线(您可能想要这样做以表明这些全局变量是“模块非公开的”) ”)。
函数名和变量名
函数名应该是小写的,单词之间用下划线分隔以提高可读性。
变量名遵循与函数名相同的约定。
mixCase 只允许在已经是流行风格的上下文中(例如 threading.py),以保持向后兼容性。
函数和方法参数
始终使用 self 作为实例方法的第一个参数。
始终使用 cls 作为类方法的第一个参数。
如果函数参数的名称与保留关键字发生冲突,通常最好附加一个尾随下划线,而不是使用缩写或拼写错误。 因此 class_ 比 clss 好。 (也许更好的是通过使用同义词来避免这种冲突。)
方法名称和实例变量
使用函数命名规则:小写,必要时用下划线分隔单词以提高可读性。
仅对非公共方法和实例变量使用一个前导下划线。
为避免与子类发生名称冲突,请使用两个前导下划线来调用 Python 的名称修改规则。
Python 将这些名称与类名混淆:如果类 Foo 具有名为 __a 的属性,则 Foo.__a 无法访问它。 (坚持的用户仍然可以通过调用 Foo._Foo__a 获得访问权限。)通常,双前导下划线应该只用于避免与设计为子类化的类中的属性发生名称冲突。
注意:关于 __names 的使用存在一些争议(见下文)。
常数
常量通常在模块级别定义,并以所有大写字母书写,下划线分隔单词。示例包括 MAX_OVERFLOW 和 TOTAL。
为继承而设计
始终决定类的方法和实例变量(统称为“属性”)应该是公共的还是非公共的。如有疑问,选择非公开;稍后将其设为公开比将公共属性设为非公开更容易。
公共属性是您希望类的不相关客户端使用的属性,并承诺避免向后不兼容的更改。非公开属性是那些不打算被第三方使用的属性;您不保证非公共属性不会更改甚至被删除。
我们在这里不使用术语“私有”,因为在 Python 中没有真正私有的属性(没有通常不必要的工作量)。
另一类属性是“子类 API”(在其他语言中通常称为“受保护”)的一部分。某些类被设计为继承自,以扩展或修改类行为的各个方面。在设计这样的类时,请注意明确决定哪些属性是公共的,哪些是子类 API 的一部分,哪些是真正仅供基类使用的。
考虑到这一点,以下是 Pythonic 指南:
公共属性不应有前导下划线。
如果您的公共属性名称与保留关键字发生冲突,请在您的属性名称后附加一个尾随下划线。这比缩写或拼写错误更可取。 (然而,尽管有这条规则,对于已知是类的任何变量或参数,尤其是类方法的第一个参数,“cls”是首选拼写。)
注 1:有关类方法,请参阅上面的参数名称建议。
对于简单的公共数据属性,最好只公开属性名称,而不是复杂的访问器/修改器方法。请记住,如果您发现一个简单的数据属性需要增加功能行为,那么 Python 提供了一条通往未来增强的简单途径。在这种情况下,使用属性将功能实现隐藏在简单的数据属性访问语法后面。
注意 1:尽量保持功能行为没有副作用,尽管缓存等副作用通常很好。
注意 2:避免将属性用于计算成本高的操作;属性符号使调用者相信访问(相对)便宜。
如果您的类打算成为子类,并且您有不希望子类使用的属性,请考虑使用双前导下划线而不是尾随下划线命名它们。这会调用 Python 的名称修改算法,其中类的名称被修改为属性名称。如果子类无意中包含具有相同名称的属性,这有助于避免属性名称冲突。
注 1:注意,在 mangled 名称中只使用了简单的类名,因此如果子类选择相同的类名和属性名,仍然会出现名称冲突。
注 2:名称修改可以使某些用途,例如调试和 __getattr__() 不太方便。然而,名称修改算法有据可查且易于手动执行。
注 3:并非每个人都喜欢名称修改。尝试平衡避免意外名称冲突的需要与高级呼叫者的潜在使用。
公共和内部接口
任何向后兼容性保证仅适用于公共接口。因此,重要的是用户能够清楚地区分公共接口和内部接口。
文档化的接口被认为是公共的,除非文档明确声明它们是临时或内部接口,免于通常的向后兼容性保证。所有未记录的接口都应假定为内部接口。
为了更好地支持自省,模块应该使用 __all__ 属性在其公共 API 中显式声明名称。将 __all__ 设置为空列表表示该模块没有公共 API。
即使适当地设置了 __all__,内部接口(包、模块、类、函数、属性或其他名称)仍应以单个前导下划线作为前缀。
如果任何包含命名空间(包、模块或类)被认为是内部的,则接口也被认为是内部的。
导入的名称应始终被视为实现细节。其他模块不得依赖于对此类导入名称的间接访问,除非它们是包含模块 API 的明确记录部分,例如 os.path 或从子模块公开功能的包的 __init__ 模块。