Effective python(一):用Pythonic的方式来思考
1,查看版本
$ python --version
或者使用sys.version_info,sys.version查看版本
2,命名风格
- 变量,函数,属性应该用小写字母拼写
- 受保护的实例属性以单个下划线开头
- 私有的实例属性应该以两个下划线开头
- 类与异常首字母使用大写字母拼写
- 模块级别常量全部使用大写形式命名
- 类实例首参数命名self,表示自身
- 类方法首参数命名cls,表示类自身
3,语句风格
- 不要通过 if len(somelist)==0 的形式判断是否为[]或“”等空值,使用if not somelist空值会自动判断为True,检测somelist是否存在值同理
- 尽量完整的写出from x import xx,如果要相对写可以from . import x等同于importx
4,bytes,str与unicode区别
- bytes是字节串,一个字节包含8位2进制数,若想将二进制数据转换为Unicode字符,则需要使用decode方法
- str包含Unicode字符,若想把Unicode字符转换为字节串(二进制数据),则需要使用encode方法
- open函数获取文件句柄,该句柄会默认以UTF-8的编码格式操作文件,open函数有一个参数encoding默认值为'utf-8',若需要读入和写入一些二进制文件,则可以将open的第二个参数设置为'wb'或'rb'而不是'w'和'r',备注:文件句柄指标识符或指针,可理解为文件描述符,指代将要操作的文件
5,将复杂的表达式制作为辅助函数,对取到的值使用if else 和 or可以设置为空情况的默认值
备注:生成器和迭代器都不占用内存,一个是凭空生成迭代,一个是数据抽出迭代
6,切片
- 切片索引越界不会报错,但使用指针访问单个元素不能越界
- 注意:当某些情况会出现切片无法正常工作,如[-n:],当n为0时变成了原列表拷贝
- 切片替换值操作不需要新值与原值个数相等如:a[2:7]=[1,2,3]
- 对赋值左侧使用切片:b=a[:]是浅拷贝,即假如a列表内有引用对象,那么更改这个引用对象,b内的这个引用对象也会被改变
- 对赋值右侧使用切片:a[:]=[1,2,3],也会浅拷贝一份替换左侧内容
- 反转字符串或数组x[::-1],但注意,这只对字节串和ASCII字符有效(即英文字符或标点),对UTF-8字符无效(即中文字符等)
7,列表,字典,集合推导式
- filter函数第一个参数是过滤条件函数,即传入x,传出bool,第二个参数是列表
- 字典推导式:d={'a':1,'b':2,'c':3} dt={x:y for x,y in d.items() }
- 集合推导式:s={n for n in d.values() }
- 双层或多层for循环列表推导式,例如将二维转一维列表:flat=[x for row in matrix for x in row],注意,for循环会按照从左到右的顺序执行,即左侧在外层,右侧在内层
- 创建矩阵列表推导式:matrix=[[x for x in range(n)] for y in range(n)]
- 列表推导式也支持多个if条件,同一循环级别中的多项条件,默认形成and表达式,如这两个表达式等效[x for x in a if x>4 if x%2==0],[x for x in a if x>4 and x%2==0]
- 每一级别for循环都可以添加条件
8,使用生成器表达式处理数据量较大的列表推导式
- 例如,读取一份文件,返回每行字符数 [len(line) for line in open('my_file.txt')],这种方法的问题就是,每一行长度都会保存在内存中
- 生成器表达式:将[]替换为()即可:it=(len(line) for line in open('my_file.txt')),它会立刻返回一个迭代器,不会深入处理文件内容,此时print(it)只会打印出一个生成器对象
- 使用生成器的方法:print(next(it)),这种方法不会保存每一次的数据到内存中,执行速度也很快
- 生成器的相互组合,roots=((x,x**0.5) for x in it),print(next(roots))
9,enumerate and zip
- enumerate第二个参数可以添加开始计数的值,默认为0
- zip封装两个或两个以上的迭代器变成生成器zip(lista,listb,listc),然后把这些平行值汇聚成元组
- 如果两个迭代器长度相同,zip不会出问题,如果长度不同,有一个耗尽zip就会终止,若不能确定zip列表是否等长,可以使用itertool中的zip_longest,它不会在乎长度是否相等
10,for和while后的else块
- 如果程序正常结束,则执行else块,如果for或while内使用break跳出,则不会执行else块
- 如果for遍历的序列是空的,或者while执行初始条件为False,都会立刻执行else块
- 尽量不要写,容易使人误解,可替代方法有很多
11,try,except,else,finally(同理,try块无执行异常执行else块),finally可以执行必须要执行的事情,如关闭句柄,退出数据库等等
可以直接留言交流问题或想法,每天都会看