1 确认python版本
2 PET 8风格
PEP 8是对Python代码格式而编订的风格指南。
空白(whitespace)
- 使用space(空格)来表示缩进,而不是tab(制表符)
- 每层缩进4个空格
- 每行字符不超过79
- 多行长表达式,除首行外要再缩进4个空格
- 函数与类之间用两个空行隔开
- 同一个类中,各方法用一个空行隔开
- 下标获取列表元素、调用函数或给关键字参数赋值的时候,不要在两旁添加空格
赋值符号左右两侧各一个空格
命名
- 函数、变量及属性应该用小写字母来拼写,单词间以下划线相连
- 受保护的实例属性,以单下划线开头,例,_leading_underscore
- 私有的实例属性,以双下划线开头,例,__double_underscore
- 类、异常,每个首字母大写,例,CapitalizedWord
- 模块级别的常量,全大写且以下划线相连,例,ALL_CAPS
- 类中的实例方法,首个参数名为 self,以表示该对象自身
类方法,首个参数名为 cls,以表示类自身
表达式和语句
- 采用内联形式的否定词,例,if a is not b 而不是 if not a is b
- if not somelist 而不是 if len(somelist)==0。空值自动评估为False
- if somelist 默认会把非空值判断为True
- 不要编写单行的if、for、while、excep语句
- import 放在文件开头
- 引入模块应使用绝对名称,例,from bar import foo 而不是 import foo
- 若一定以相对名称来编写import语句,应采用明确地写法:from.import bar
- import顺序:标准库、第三方、自用 三部分模块。各部分按字母排序
3 了解bytes、str与Unicode的区别
没看懂
4 用辅助函数来取代复杂的表达式
if/else表达式比or或and写成的表达式清晰
5 了解切割序列的办法
- 基本切片操作: somelist[start:end],且含start,不含end。
- 切割列表时不计较索引是否越界。这可用于限定输入序列的最大长度,例如、,a[:20]或a[20:]。访问列表时,下标不可越界
- 切割后,会产生另外一份全新的列表。新列表的修改,不会影响原列表。
b=a[:] #b is not a
c=a #c is a
6 单词切片操作内,不要同时指定start、end和stride
- 进式切片: somelist[start:end:stride]。可以指定步进值(stride)
- stride 可以为负,但尽量避免。-1可反转list。
- 不要同时使用start、end和stride。可以拆解成两条:一条做范围切割,一条做步进切割,或考虑内置itertool模块中的islice。
7 用列表推导来取代map和filter
列表推导(list comprehension):根据一份列表来制作另一份。同时指定索要迭代的输入序列,以及计算新列表中每个元素的值所用的表达式。
a=[1,2,3,4]
s1=[x**2 for x in a]
>>> [1,4,9,16]
s2=[x**2 for x in a if x % 2 == 0]
>>>[4,16]
字典(dict)和集(set)也有和列表类似的推导机制
cr={'g':1,'h':2}
rc={r:c for c,r in cr.items()}
ls={len(n) for n in rc.values()}
print (rc,ls)
>>>({1: 'g', 2: 'h'}, set([1]))
8 不要使用含有两个以上表达式的列表推导
列表推导支持多重循环。
例如,把矩阵(列表的列表)简化为一维列表
m=[[1,2],[3,4]]
f=[x for row in m for x in row]
print (f)
>>>[1,2,3,4]
例如,
s=[[x**2 for x in row] for row in m]
>>>[[1, 4], [9, 16]]
列表也支持多个if条件
fi=[x for x in f if x>2 if x % 2==0]`
print (fi)
>>>[4]
- 列表推导支持多级循环,每一级循环也支持多项条件
- 超多两个表达式的列表推导是很难理解的,应该尽量避免。
9 用生成器表达式来改写数据量较大的列表推导
数据大较大,列表推导可能会占用过多的内存。由生成器表达式所返回的迭代器,可以逐次产生输出值,避免内存用量的问题。
#将列表推导的中括号改成小括号,就成了生成器的表达式
it=(len(x) for x in open ('my_file.txt'))
#it是一个迭代器
#逐次调用内置的next函数,返回迭代器对应的参数
print (next(it))#输出下一个值
print (next(it))#输出下一个值
10 enumerate 取代range
既要元素,还要索引时,
for i in range(len(somelist)):
s=somelist[i]
#另一种实现方式,n可指定开始计数的值,缺省为0
for i,s in enumerate (somelist,n):
pass
enumerate 可把迭代器包装成生成器,生成器每次产生一对输出值,前者表示下标,后者表示序列元素。
11 zip函数遍历两个迭代器
names=['abc','defg']
ls=[len(n) for n in names]
for name, l in zip (names, ls):
pass
- Python 3 中的zip相当于生成器,会在遍历过程中逐次产生元组,而Python 2 则是直接把这些元组完全生成好,一次返回。
- 迭代器长度不等,zip就会提前终止
- itertools内置模块中的zip_longest ( Python 2 中为izip_longest)
12 不在循环后写else块
- 语法上,for和while循环后,可以紧跟else块。循环没有遇上break时,else才会执行
- 尽量不要使用else块
13 合理利用try/except/else/finally
- 无论try块是否发生异常,都可用finally块来执行清理工作
- try块没有发生异常,就执行else块,可执行在代码清理(finally块)前的操作
- except块针对可能发生的异常,分别执行相应的操作
def ljk(data,key):
try:
r=j.loads(data)
except ValueError as e :
raise KeyErro from e #这句啥意思?
else:
return r[key]