条款总览
用Pythonic方式来思考
1、确认自己所用的Python版本
2、遵循PEP 8 风格指南
3、了解bytes、str与unicode的区别
4、用辅助函数来取代复杂的表达式
5、了解切割序列的方法
6、在单次切片操作内,不要同时指定start、end和stride
7、用列表推导取代 map 和 filter
8、不要使用含有两个以上表达式的列表推导
9、用生成器表达式来改写数据量较大的列表推导
列表推导方法:
生成器表达式是对列表推导和生成器的一种泛化。
输入数据量较大时,列表推导可能会因为占用太多内存而出问题 。有生成器表达式所返回的迭代器,可以逐次产生输入值,从而避免了内存用量问题。把某个生成器表达式所返回的迭代器,放在另一个生成器表达式的for子表达式中,可将二者组合起来。串在一起的生成器表达式执行速度更快。
10、尽量用enumerate取代range
enumerate函数提供了一种精简的写法,可以在遍历迭代器时获知每个元素的索引。尽量用enumerate来改写那种将range与下标访问相结合的序列遍历代码。可以给enumerate提供第二个参数,以指定开始计数时所用的值(默认值是0)
11、用zip函数同时遍历两个迭代器
12、不要在for和while循环后面写else块
13、合理利用try\except\else\finally结构中的每个代码块
无论try块是否发生异常,都可以利用try/finally复合语句中的finally块来执行清理工作。else块可以用来缩减try块中的代码量,并把没有发生异常时所要执行的语句与try/except代码块隔开。顺利运行try块后,若想使得某些操作能在finally块的清理代码之前执行,则可将这些操作写到else块中。
函数
14、尽量用异常来表示特殊情况,而不要返回None
15、了解如何在闭包里使用外围作用域中的变量
对于定义在某作用域内的闭包来说,它可以引用这些作用域中的变量。使用默认方式对闭包内的变量赋值,不会影响外围作用域中的同名变量。在Python3中,程序可以在闭包内用nonlocal语句来修饰某个名称,使得该闭包能够修改外围作用域中的同名变量。除了一些比较简单的函数,尽量不要使用nonlocal语句。
16、考虑用生成器来改写直接返回列表的函数
17、在参数上面迭代时,要多加小心
18、用数量可变的位置参数减少视觉杂讯
在def语句中使用args,即可令函数接受数量可变的位置参数。调用函数时,可以采用操作符,把序列中的元素当成位置参数, 传给该函数。对生成器使用操作符,可能导致程序耗尽内存并崩溃。在已经接受 args参数的函数上面继续添加位置参数,可能会产生难以排查的bug。
19、用关键字参数来表示可选的行为
函数参数可以按位置或关键字来指定。只使用位置参数来调用函数,可能会导致这些参数值的含义不够明确,而关键字参数则能够阐明每个参数的意图。给函数添加新的行为时,可以使用带默认值的关键字参数,以便与原有的函数调用代码保持兼容。可选的关键字参数,总是应该以关键字形式来指定,而不应该以位置参数的形式来指定。
20、用None和文档字符串来描述具有动态默认值的参数
参数的默认值,只会在程序加载模块并读到本函数的定义时评估一次,对于{}或[]等动态的值,这可能会导致奇怪的行为。对于以动态值作为实际默认值的关键字参数来说,应该把形式上的默认值写为None,并在函数的文档字符串里描述该默认值所对应的实际行为。
21、用只能以关键字形式指定的参数来确保代码明晰
实现方法:
关键字参数能够使函数调用的意图更加明确。对于各参数之间很容易混淆的函数,可以声明只能以关键字形式指定的参数,以确保调用者必须通过关键字来指定它们。对于接受多个Boolean标志的函数,更应该这样做。
类与继承
22、尽量用辅助类来维护程序的状态,而不要用字典和元组
不要使用包含其他字典的字典,也不要使用过长的元组。如果容器中包含简单而又不可变的数据,那么可以先使用namedtuple来表示,待稍后有需要时,再修改为完整的类。保留内部状态的字典如果变得比较复杂,那就应该吧这些代码拆解为多个辅助类。
23、简单的接口应该接受函数,而不是类的实例
对于连接各种Python组件的简单接口来说,通常应该给其直接传入函数,而不是先定义某个类,然后再传入该类的实例。Python中的函数和方法都可以像一级类那样引用,因此,它们与其他类型的对象一样,也能够放在表达式里面。通过名为call的特殊方法,可以使得该类的实例能够像普通的Python函数那样得到调用。如果要用函数来保存状态,那就应该定义新的类,并令其实现call方法,而不要定义带状态的闭包。
24、以@classmethod形式的多态去通用地构建对象
Python程序中,每个类只能有一个构造器,也就是init方法。通过@classmethod机制,可以用一种与构造器相仿的方式来构造类的对象。通过类方法多态机制,我们能够以更加通用的方式来构建并拼接具体的子类。
25、用super初始化父类
Python使用标准的方法解析顺序来解决超类初始化次序及钻石继承问题。总是应该使用内置的super函数来初始化父类。