《流畅的python》这本书值得推荐,认真读完2篇,对python的理解提高一大截。本书属于python进阶书,不适合入门读物。另外还有2本进阶书《python cookbook》和《Effective Python:编写高质量Python代码的59个有效方法》。下面是本书的读书笔记,其他2本后面陆续补充。
一些零散小知识
特殊函数:
func,称为双下方法,也是特殊方法或者魔术函数等,是专门给python解释器使用的,自己不要直接使用,而是转换为使用相应的正常函数。比如
len()函数对应的是len()
我们自己经常时间的特殊函数是__init__
python会忽略[] {} ()中的换行,所以可以不加\符号来换行
_占位符
for country, _ in traveler_ids:
*符号可迭代元素拆包、替代多余元素
*(1,2,3,4), *可以拆成单个元素
a, *body, c,d = range(5), *用于处理剩下元素
*对序列复制
[1,2,3]*2,复制2份[1,2,3,1,2,3]
None关于是否返回新对象与返回值是否为None编程规范
如果一个函数是在原对象上面修改,而无需返回值,这时可以返回None表示程序执行成功。
dict和set都是无序的,不应该一遍迭代一遍修改,会混乱,因为添加新键会导致已有键顺序错乱。
dict和set可以散列,所以查找速度非常快。list不可以散列查找速度很慢。但是散列对象是以空间换时间,占用存储空间很大。
什么是可散列对象:
1、支持hash()函数,且通过__hash__返回值不变
2、支持通过__eq__判断相等
3、若a==b,那么hash(a)==hash(b)
__doc__属性用于形成对象的帮助文本,比如给IDE环境使用,比如help(obj)显示
对象引用
关于变量的错误理解是存储数据的盒子。
关于变量的正确理解是对象的引用,是附加在对象上的标注。像便利贴
所以定义一个变量进行赋值,更像把变量贴到对象上。
别名:一个对象可以有多个标签
is判断相等性
is判断的实质是id()两个对象的一致,id在对象的生命周期中不会变化。而不仅仅是内容相等。相等的==对象未必是同一个对象
==判断的是对象的值
is判断的是对象的id
is运算速度比==快,is经常用于判断是否为None,x is None
元组是对象的引用,如果元组引用的对象是可变对象,那么元组内容也是可以变化的。比如一个列表组成的元组。
浅复制和深复制:
copy.copy()和copy.deepcopy()分别为浅复制和深复制
浅复制只复制第一层对象引用,深复制会进一步复制深层的引用。尤其针对第二层是可变对象时。
函数参数的引用
python唯一支持的参数传递模式是共享传参。即一个函数的形参获取的是实参引用的副本,函数体内对形参的修改其实也会修改实参数据。
千万不要使用可变类型作为参数的默认值
比如不要这样做:def __init__(self, passenger=[]),这样做后果是在模块加载时就会创建这个空列表,导致所有的不带参数的实例化对象都使用同一个列表引用。
推荐做法 def __init__(self, passenger=None) 然后在函数体内部判断如果为None再创建一个新的空列表
del和垃圾回收
del仅仅删除对象的引用,而不是对象本身,对象本身只有当该对象所有的引用都没有了之后才会被系统当做垃圾进行回收。
wreakref弱引用
不增加引用的计数,经常用在缓存中。
import weakref
a_set={0,1}
wref=weakref.ref(a_set)
a_set={2,3,4} {0,1}的引用清0
wref()就会因为原来引用的{1,2}被回收而导致清空。
WeakValueDictionary和WeakKeyDictionary
两者也主要用于缓存,也是weakref里面的类。当弱引用的值或key被回收后,字典里对应的键与值也会自动被删除。
另外,注意不是所有类型都可以做弱引用,比如dict, list,int,tuple都不可以作为弱引用。但自己定义的对象可以。
下面是一些使用细节:
1、简单的赋值语句不创建副本
2、+=,-=等增量运算,如果左边是不可变类型会创建新对象,如果左边是可变类型会在原来对象上面修改
3、对象的重新赋值相当于重新绑定,原来老的对象如果引用数为0会被回收
函数
函数是对象,函数是function类的实例
高阶函数:将函数作为参数,或者将函数作为结果返回
匿名函数lambda,python对lambda的支持有限制,不能在定义体中使用赋值、while、for等语句。
格式:lambda x : x in list
可调用对象
怎么判断一个对象是否可以用()进行调用,用callable(),如果一个类实现了__call__方法,类的对象就是可调用对象
7种可调用对象:
自定义函数、内置函数、内置方法、方法、类、类的实例、生成器函数
位置参数和关键字参数的传入方法*和**
传入未知个数的位置参数用*args,所有参数会存为一个元组
传入未知个数的关键字参数用**kwargs,所有参数被存为一个字典
怎么将构造好的参数列表作为一个参数传递给函数,func(**args),args可以是一个字典,里面包含了func所需的所有参数,**会把这些参数作为一个参数传入。
func会自动解析,多余的参数会传给**kwargs关键字参数
仅限关键字参数是python3特性,需要放在*args后面,**kwargs前面,比如func(name,*args, address="SH", **kwargs)
这样address只能接收关键字参数,关键字参数如果不设置默认值,那么调用的时候必须传入参数
如果仅想支持仅限关键字参数,而不想支持数量不定参数,可以用*号替代*args
函数注解
def clip(text:str, max_len:'int > 0'=80) -> str:
参数注解放在参数后面:
有默认值时的注解在参数和默认值=号之间
返回值注解是在函数:前
函数注解是给IDE等解释器或者代码检测用,不影响解释器执行。
这些注解都会存储在__annotations__属性中,使用inspect.signature()可以检查
字符码位与编码
码位:是01114111的十进制数字,Unicode标准是用46个十六进制数表示,如U+0041,这个称为码位
编码:将码位转成字节序列。不同编码会将相同码位转成不同的字节序列。相反过程叫解码。
默认编码:python3默认使用utf-8编码源代码,python2默认使用ascii。linux一般用utf-8,window一般默认是cp1252。推荐不要用默认编码,自己显示指定编码方式。
过程:码位 <–> 编码解码 <–> 字节序
编码错误处理方法UnicodeEncodeError
city.encode(‘cp437’, errors=‘ignore’)
ignore遇到无法编码字符忽略,
replace遇到无法编码的替换成?问号
xmlcharrefreplace遇到无法编码的替换成xml实体
还有一种处理错误方式:linux下是surrogateescape,windows是strict
str.encode(‘ascii’, ‘surrogateescape’)这个会用特殊码位替换错误码位
小字节序和大字节序
小字节序设备中,各个码位的最低有效字节在前面。比如字母E的码位是U+0045,在小字节序中45会在前面,00会在后面。
UTF-16编码序列开头会有BOM字符0xff和0xfe,表示使用的是Intel CPU小字节序
UTF-8编码不管机器是那种字节序,生成的字节序都是一样的,所以可以不需要BOM字节,但是也可以加,不是强制。
Unicode字符串的比较
Unicode存在组合字符(变音符号和附加到前一个字符上的记号,打印时作为一个整体,导致字符串比较复杂
unicodedata.normalize()是Unicode规范化函数,将字符串规范化后再比较。第一个参数有下面几种类型
NFC(Normalization Form C) 使用最少的码位构成等价字符串,也是W3C推荐的规范化形式,清洗文本时经常用到
NFD 把组合字符分解成基字符和单独的组合字符
NFKC、NFKD,K指兼容意思,比如1/2,2次方等一个字符的会被转义成1/2三个字符。会对源数据有损失,所以不用于数据存储,而是用于索引和搜索中。
from unicodedata import normalize, name, combining
normalize('NFC',name) 规范化
combining(name)判断是否为组合字符
name('\u0043') 显示unicode字符的名称
str.casefold()
大小写折叠,类似str.lower(),但对特殊字符处理不同。比如微子符u变成小写u,大约有116个特殊字符
对于不区分大小写的比较最好使用这个函数
Unicode字符串的排序
ASCII字符排序用sorted()
非ASIC字符用sorted(name, key=local.strxfrm),但前提是要先设置自己的区域:
import local #这是一个第三方库
local.setlocal(local.LC_COLLATE, 'pt_BR.UTF-8')
PyPI pyuca库:一个专门库用于unicode排序:
import pyuca
coll = pyuca.Collator()
sorted(name, key=coll.sort_key)
另外PyPI库中的regex模块对unicode支持性更好,用于取代内置的re模块
数据结构
列表 list [] 可写、有序、不可散列
元组 tuple () 不可写、有序、可重复
字典 dict {key:value} 可写、无序、可散列,key不可重复
集合 set {} 可写、无序、不重复
容器序列
list, tuple, collcetions.dequ