以实践为基础
测试驱动开发TDD:精髓就是先写测试,对自定义类的每一个方法都编写doctest。
核心语言特性:迭代、切片。Talk is cheap. Show me the code.
1 Python数据模型
单下划线:放在名称前,表示其属性为“私有”;在解释器中,指代上一条语句的结果;
双下划线:放在方法名的前面,被认为是“_className__methodName”,不能被改变;放在名称的前、后,表示内置的特殊方法名
内置函数repr
,把一个对象用字符串形式表达;str
方法返回的字符串对终端用户更友好。(即%r & %s)
特殊方法一览表:敲代码过程中,逐渐熟悉。对序列数据类型的模拟,是特殊方法使用最多的地方。
2 数据结构
列表推导 list comprehension
(等同于map/filter
)
生成器表达式 generator expression
语法:把方括号换成圆括号;逐个产出元素,更节省内存;不要把可变对象放在元组里面。
Python惯例:如果一个函数或者方法对对象进行了就地改动,那它就应该返回None,传入参数有变动,并且未产生新对象。
sorted
新建一个列表作为返回值,接受任何的可迭代对象,包括不可变序列、生成器,最后一定返回列表。
bisect
管理已排序的序列(搜索、插入)
列表的替换类型
array.array
只包含数字的列表
memoryview
用不同的方式读写同一块内存,能在不复制内容的情况下操作同一个数组的不同切片
numpy.ndarray
NumPy/SciPy专为线性代数、数值积分和统计学而设计
collections.deque
快速从两端添加或者删除元素
容器序列
list, tuple, collections.deque
存放任意类型的对象的引用
扁平序列
str, bytes, bytearray, memoryview, array.array
存放字符、字节、数值等基础类型,是一段连续的内存空间
元组
# 拆包
_, filename = os.path.split('/home/luciano/.ssh/idrsa.pub')
# 具名元组
City = collections.namedtuple('City', 'name country population coordinates')
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
切片、区间左闭右开的原因
符合以0为起始下标的传统;快速计算元素的个数;可以用任意一个下标,把序列分隔成不重叠的两部分,即myLst[:x] & myLst[x:]
字典、集合、散列表
集合 许多唯一对象的聚集;大括号。
# 用于所有可迭代对象
found = len(set(needles) & set(haystack))
found = len(set(needles).intersection(haystack))
字典推导 dict comprehension; 集合推导 setcomps
# 元组的列表
country_code = {country: code for code, country in DIAL_CODES}
# 比get(),多一步操作:键不存在,则添加键-默认值;很实用!
wordCountDict.setdefault(word, [])
字典的替换类型
collections.OrderedDict/ChainMap/Counter/UserDict
划重点!
- 稀疏:总是有空白元素的数组。
- 不管查询有多少个元素的字典或集合(不超过内存大小),所耗费的时间都能忽略不计。
- 但字典在内存上的开销巨大;存放数量巨大的记录,最好放在由元组或具名元组构成的列表中:第一是避免了散列表所耗费的空间,第二是无需把记录中字段的名字在每个元素里都存一遍。
- 往字典里添加新键有可能改变已有键的顺序:所以不要对字典同时进行遍历和修改,最好分两步进行。
文本和字节序列
bytes/bytearray
构造方法要求的传参:str + encoding; 可迭代对象 + 0~255; 已实现缓冲协议的对象
Unicode三明治:尽早把输入的字节序列解码为字符串;只处理字符串对象;尽量晚把字符串编码为字节序列(文本)。
在多台设备、多种场合下运行的代码,一定不能依赖默认编码,明确传入encoding=
参数。
3 函数即对象
高阶函数 map/reduce/filter
callable()
7类可调用对象
类的call方法:让类的实例作为函数调用——‘快捷方式’
函数内省:一些默认参数
传参:*content
存入元组;**attrs
存入字典;仅限关键字参数
注解(python 3):传参text:str;函数clip()->str;类或者字符串
装饰器是语法糖。把被装饰的函数替换成其他函数;在加载模块时立即执行。
被装饰的函数只在明确调用时运行(区别:导入、运行)
多数装饰器都会修改被装饰函数;先定义一个内部函数,然后将其返回,替换被装饰函数。
functools.lru_cache
备忘;singledispatch
泛函数;
python不支持重载方法或函数?
闭包,指延伸了作用域的函数,关键在于能访问定义体之外定义的非全局变量。
闭包是一种函数,它会保留定义函数时存在的自由变量的绑定。
nonlocal
(python 3):把变量标记为自由变量
4 面向对象思维(第8-13章)
引用式变量:正确理解“把变量s分配给seesaw”“变量只是附加在对象上的标注”
id函数、is比较对象的标识(运算速度快,x is None);==比较对象的值
默认浅拷贝:构造方法或[:];最外层容器
任意对象的深、浅拷贝:copy.deepcopy()
、copy.copy()
不要使用可变类型作为参数默认值,如[];防止调用方修改可变参数
垃圾回收:引用计数归零,对象立即被销毁。每个对象都会统计有多少引用指向自己。
classmethod
装饰器
格式化显示:format_spec 格式规范微语言(各个类自行扩展:format方法
format(rmb, '0.2f') '1 RMB = {rate:0.2f} USD'.format(rate=rmb)
默认format(obj) = str(obj)
私有属性避免继承:_Vector2d__x “名称改写”
更加pythonic:创建一个子类,只用于定制类的数据属性
第10章 多维向量
网友评论