4.1 PEP 8 和命名最佳实践
4.2 命名风格
Python中命名风格有:
- 每个单词首字母大写:CameCase
- 第一个单词首字母小写其他单词首字母大写:mixedCase
- 大写:UPPERCASE和带下划线的大写:ER_CASE_WITH_UNDERSCORES
- 小写:lowercase和带下划线的小写:lower_case_with_underscores
- 前缀:_leading和后缀:trailing_,或者都加下划线:_doubled_
使用下划线通常是缩写词。前缀和后缀下划线用来标记私有和特殊的元素
这些风格将被应用到:
- 变量
- 函数和方法
- 属性
- 类
- 模块
- 包
4.2.1 变量
变量有两种:常量、公有和私有变量
1. 常量
Python中对不会发生改变的全局变量(常量),使用大写和下划线:
MAX_SIZE = 1024
Python中并没有常量,任何变量都是可以改变的,只是约定一个常量来使用。
即便是冗长的名称,但是能更好的理解:
ALL_WORDS_OF_FILE = 1024
使用常量时,将它们集中放在模块的头部是一个好办法。
2. 命名和使用
对于张的像标志的选项,将它们和布尔操作组合是一种好方法:
In [1]: WHITE = 1 << 1
In [2]: BLUE = 1 << 2
In [3]: RED = 1 << 3
In [4]: def has_options(options, name):
...: return bool(options & name)
...:
In [5]: SET = BLUE | RED
In [6]: has_options(SET, BLUE)
Out[6]: True
In [7]: has_options(SET, WHITE)
Out[7]: False
In [8]: has_options(SET, RED)
Out[8]: True
每个值左移一位保证不会重复,使用'|'组合多个数字,使用'&'判断是否在其中。
3. 公有和私有变量
易变的私有变量和全局变量,当需要给保护时应该使用小写和一个前下划线。
In [12]: _observers = []
In [13]: def add_observer(observer):
....: _observers.append(observer)
....:
In [14]: def get_observers():
....: return tuple(_observers)
....:
- 对于函数和方法中的变量也是如此。
- 对于类或实例变量,作为公共的一部分,并且不能带来任何有用的信息或者冗余的情况下必须使用私有标志
只支持一个属性的特性是好的私有成员:
In [17]: class Citizen(object):
....: def __init__(self):
....: self._message = 'Go boys'
....: def _get_message(self):
....: return self._message
....: kane = property(_get_message)
....:
In [18]: Citizen().kane
Out[18]: 'Go boys'
另一个就是对于只在类内部使用的变量要加上前下划线:
class TakePhoto(object):
def __init__(self):
self._people = []
def add_person(self, name):
self._people.append(name)
def save_photo(self):
for per in self._people:
print per
4.2.2 函数和方法
函数和方法命名时应该使用小写和下划线。
1. 关于私有元素的争论
- 别使用前置双下划线表示私有特性
- 不要大写和下划线混搭表示私有特性
2. 特殊方法
- 不要使用_method_这样的特殊命名法。它们被用于操作符重载、容器定义等。它们应该被集中放在类定义的最前面
3. 参数
- 参数使用小写,如果需要可以加上下划线
4.2.3 属性
属性名称是小写或者小写加上下划线命名,可以是一个名词或者一个形容词,也可是一个小短语:
4.2.4 类
类名使用首字母大写的命名规则,类和实例变量常常是名词短语,私有类可以加上前下划线。
4.2.5 模块和包
模块名称都使用不带下划线的小写字母命名,当模块对于包是私有的时候,将添加一个前下划线。编译过的C或C++模块名称通常带有一个下划线并且将带入纯的Python模块中。
4.3 命名指南
4.3.1 使用“has”或“is”前缀命名布尔元素
当一个元素使用起来是保存布尔值的时候,使用“is”和“has”前缀提供一个自然的方法,这样更容易理解:
In [35]: class File(object):
....: def __init__(self, filename):
....: self._filename = filename
....: self.is_open = False
....: def open_file(self):
....: self.is_open = True
....: def has_open(self):
....: return self.is_open
....:
In [36]: file = File("content.txt")
In [37]: file.open_file()
In [38]: file.has_open()
Out[38]: True
4.3.2 使用复数形式命名序列元素
一个元素用来保存一个序列时,用复数形式命名:
In [39]: class DB(object):
....: connected_users = ['Tarek']
....: tables = {'Customer' : ['id', 'first_name', 'last_name']}
....:
4.3.3 用显示的名称和命名字典
变量用来保存一个映射时,使用显示的名称:
In [42]: person_address = {'Bill':'655 Monty Road', 'Pamela':'45 Python street'}
In [43]: person_address['Pamela']
Out[43]: '45 Python street'
4.3.4 避免通用名称
不要使用诸如list、dict、sequence、elements会使得代码难以阅读理解和使用。避免使用内建的名称,防止带当前的命名空间被遮蔽。
#不好的命名
In [45]: def compute(data):
....: for element in data:
....: yield element * 12
....:
#好的命名
In [46]: def display_numbers(number):
....: for number in numbers:
....: yield number * 12
....:
4.3.5 避免现有的名称
对关键字而言加上一个后下划线是一种解决方法,class常常被改成klass或cls。
4.4 参数的最佳实践
参数设计的三个原则:
- 根据迭代设计构建参数
- 信任参数和测试
- 小心是使用魔法参数*arg和 **kw
4.4.1 根据迭代设计构建参数
一个函数有固定的、精心的设计参数列表会使代码更健壮。这往往需要多个版本的迭代设计来构建。它们应该反应创建该所有针对的使用场景。
4.4.2 信任参数和测试
小心使用断言
4.4.3 小心是使用魔法参数*arg和 **kw
- 魔法参数或破坏函数或者方法的健壮性,会变成一个脆弱的函数或者方法。
- 如果你的参数列表很长而且很复杂,魔法参数很有诱惑力,但是这个函数更应该被分解或者重构
4.5 类名
类名必须简洁、精明,并足以从中理解类所完成的工作。应该使用表示其特性的类型或者特性的后缀.
- SQLEngine
- MimeTypes
- StringWidget
- TestCase
基类可以使用Base或Abstract,例如: - BaseCookie
- AbstractFormatter
4.6 模块和包的名称
模块和包的名称中,应该体现出其内容和用途。名称要简短、使用小写字母,不使用下划线。
如果是一个协议的实现通常使用lib:
- smtplib
- urllib
- telnetlib