part1.编写高质量Python代码的59个有效方法

PS:整理自书籍《Python 编写高质量Python代码的59个有效方法》,仅供学习整理使用

Cha 1 用Pythonic方式来思考

TIP 1 确认自己所用的Python版本

TIP 2 遵循PEP8风格指南

1.使用space来表示缩进,而不要使用tab

2.文件中的函数和类之间应该用两行空格隔开

3.在同一个类中,各方法之间应该用一个空行隔开

4.在使用下标来获取列表元素,调用函数或给关键字参数赋值的时候,不要在两旁添加空格

5.函数变量及属性应该用小写字母来拼写,各单词之间以下划线相连,例如,lowercase_underscore

6.受保护的实例属性,以单个下划线开头,例如,_leading_underscore

7.私有的实例属性,应该以两个下划线开头,例如,__double_leading_underscore

8.类与异常,应该以每个单词首字母均大写的形式来命名,例如,CapitalizedWord

9.模块级别的常量,应该全部采用大写字母来拼写,各个单词之间以下划线相连,例如。ALL_CAPS

10.类中的实例方法,应该吧首个参数命名为self,以表示该对象自身

11.类方法的首个参数,应该命名为cls,以表示该类自身。

12.每行的字符数不应超过79,可用反斜线和小括号进行多行代码的连接

13.对于占据多行的长表达式来说,除了首行之外的其余各行都应该在通常的缩进级别上再加4个空格

14.采用内联形式的否定词,而不要把否定词放在整个表达式的前面

15.不要通过检测长度的办法来判断是否为空值

16.关于模块的引入

TIP 3 了解bytes,str与unicode的区别

TIP 4 用辅助函数来取代复杂的表达式

1.开发者很容易过度运用Python的语法特性,写出特别复杂并且难以理解的单行表达式。

2.把复杂的表达式移入辅助函数之中。

3.使用if、else表达式,比使用or或者and的Boolean操作符写成的表达式更加清晰

TIP 5 了解切割序列的办法

1.不要写多余的代码:当start索引为0,或end索引为序列长度时,应该将其省略

2.切片操作不会计较start与end是否越界

3.对list赋值的时候,如果使用切片操作,就会把原列表中处在相关范围内的值替换成新值,即便长度不同亦可替换。

TIP 6 在单次切片操作内,不要同时指定start、end、和stride

1.既有start ,end又有 stride的切割操作,可能会令人费解。

2.尽量使用stride为正数,且不带start或end索引

3.在同一个切片操作内,不要同时使用start,end和stride,如果确实需要执行,考虑将其拆解为两条赋值语句,其中一条范围切割,另一条做步进切割,或考虑使用内置itertools模块中的islice

TIP 7 用列表推导来取代map和filter

a = [1,2,3,4,5,6,7,8]

square = [x**2 for x in a]

print(square)

1.列表推导要比内置的map和filter函数清晰,因为它无需额外编写lambda表达式

2.列表推导可以跳过输入列表中的某些元素,如果改用map来做就必须辅以filter方能实现

3.字典与集合也支持推导表达式

TIP 8 不要使用含有两个以上表达式的列表推导

eg: matrix = [[1,2,3],[4,5,6],[7,8,9]]

flat = [x for row in matrix for x in row]  

squared = [[x**2 for x in row] for row in matrix]

print(flat)  # flat = [1,2,3,4,5,6,7,8,9]

print(squared) # squared = [[1,4,9],[16,25,36],[49,64,81]]

条件语句亦可加入至列表推导式

a = [1,2,3,4,5,6,7,8,9,10]

b = [x for x in a if x > 4 if x % 2 == 0]

c =  [x for x in a if x > 4 and x % 2 == 0]

此处if 和 and作用一样,b和c的结果等价

1.列表推导支持多级循环,每一级循环也支持多项条件

2.超过两个表达式的列表推导很难理解,应该尽量避免

TIP 9 用生成器表达式来改写数据量较大的列表推导

列表推导的缺点:在推导过程中,对于输入序列的每个值来说,可能都要创建仅含一项元素的全新列表,当数据非常多时,可能会消耗大量内存,导致程序崩溃。

按照列表推导的写法写迭代器,将中括号换成小括号,即可得到迭代器,结合next函数生成所需要的值。

eg: it = (len(x) for x in open('/tmp/my_file.txt'))

print(it)

print(next(it))

1.当输入的数据量较大时,列表推导可能会因为占用太多内存而出问题

2.由生成器表达式所返回的迭代器,可以逐次产生输出值,避免内存用量问题

3.把某个生成器表达式所返回的迭代器,放在另一个生成器表达式的for子表达式中,即可将二者组合起来

4.串在一起的生成器表达式执行速度很快

TIP 10 尽量用enumerate取代range

1.enumerate函数提供了一种精简的写法,可以在遍历迭代器时获知每个元素的索引

2.尽量用enumerate来改写那种将range与下标访问相结合的序列遍历代码

3.可以给enumerate提供第二个参数,以指定开始计数时所用的值(默认为0)

TIP 11 用ZIP函数同时遍历两个迭代器

1.内置的zip函数可以平行地遍历多个迭代器

2.Python3的zip相当于生成器,会在遍历过程中逐次产生元祖,而Python2中的zip则是直接把这些元祖完全生成好,并一次性返回整份列表。

3.如果提供的迭代器长度不等,那么zip就会自动提前终止

4.itertools内置模块中的zip_longest函数可以平行遍历多个迭代器,而不用在乎它们的长度是否相等。

TIP 12 不要在for和while循环后面写else块

1.Python有种特殊语法,可在for及while循环的内部语句块之后紧跟一个else块

2.只有当整个循环主体都没遇到break语句时,循环后面的else块才会执行

3.不要在循环后面使用else块,因为这种写法既不直观又容易引起误解

TIP 13 合理利用try/except/else/finally结构中的每个代码块

try/finally结构,确保程序能够可靠地关闭文件句柄。

handle = open('/tmp/random_data.txt')

try:

    data = handle.read()

finally:

    handle.close()

1.无论try块是否发生异常,都可以利用try/finally复合语句中的finally块来执行清理工作

2.else块可以用来缩减try块中的代码量,并把没有发生异常时所要执行的语句与try/except代码块隔开

3.顺利运行try块后,若想使某些操作能在finally块的清理代码之前执行,则可将这些操作写到else块中。

你可能感兴趣的:(part1.编写高质量Python代码的59个有效方法)