流畅的python第一章 数据模型 第二章序列构成的数组 第三章字典和集合

第一章数据模型

random.choice
choice(序列)随机重一个序列中选一个值
python内置的complex可以用来表示二维向量
向量对象的构造函数只接受数值,不接受字符串。
str__和__repr 的区别在于,前者是在str()函数被使用,或者在用print函数打印一个对象时才被调用的,并且它返回的字符串对终端用户较友好。如果你只想实现这两个特殊方法中的一个,__repr__是更好的选择,因为如果一个对象没有__str__函数,而python又需要调用它的时候,解释器会用__repr__做为替代。
算术操作符:通过__add__和__mul__为+和*运算时调用的。这两个方法返回值都是新创建的向量对象,被操作的两个向量还是原封不动,代码里只是读取了他们的值而已。
为了判定一个值为真还是假,python会调用bool(x),而这个函数会调用x.bool()的结果。如果__bool__不存在,就会尝试调用x.len()。

特殊方法一览

1 跟运算符无关的特殊方法

字符串/字节序列表示形式: repr str format bytes
数值转换: abs bool complex init float hash index
集合模拟: len getitem setitem delitem contains
迭代枚举: iter reversed next
可调用模拟: call
上下文管理: enter exit
实例创建和销毁: new init del
属性管理: getattr getattribute setattr delattr dir
属性描述符: get set delete
跟类相关的服务: prepare instancecheck subclasscheck

2 跟运算相关的特殊方法

一元运算符: neg - ,pos + , abs abs()
众多比较符: lt < , le <= ,eq == ,ne != , gt > ,ge >=
算术运算符: add +,sub -.mul * ,truediv / ,floordiv // , mod % ,divmod divmod() , pow **或pow() , round round()
位运算符: invert ~ ,lshift << ,rshift >> , and & ,or | , xor ^

第二章 序列构成的数组

python标准库用C实现了丰富的序列类型:
容器序列: list tuple 和collections.deque 这些序列能存放不同类型的数据
扁平序列: str bytes bytearray memoryview和array.array,这类序列只能容纳一种类型。
容器序列存放的是他们所包含的任意类型的对象的引用,而扁平序列存放的是值而不是引用。扁平序列其实是一段连续的内存空间。
序列类型还能安装能否被修改类分类: 可变序列和不可变序列
列表推导式是构建列表的快捷方式,而生成器表达式则可以用来创建其他任何类型的序列。listcomps:列表推导式 genexps: 生成器表达式。

具名元组

collections.namedtuple:是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类,这个带名字的类对调试程序有很大帮助。用namedtuple构建的类的实例所消耗的内存跟元组是一样的,因为字段名都被存在对应的类里面。这个实例跟普通的对象实例比起来也要小一些,因为python不会用__dict__来存放这些实例的属性。
1 创建一个具有元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。
2 存放在对应字段里的数据要以一串参数的形式传入到构造函数中(注意,元组的构造函数切只接受单一的可迭代对象)
3 你可以通过字段名或位置来获取一个字段的信息。
具名元组还有一些自己的属性:_fields类属性 类方法_make(iterable)和实例方法_asdict()
_fields属性是一个包含这个类所有字段名称的元组。
用_make()通过接受一个可迭代对象来生成这个类的一个实例。
_asdict()把具名元组以collections.Ordereddict的形式返回,我们利用它来吧元组里的信息友好的呈现出来.
from collections import namedtuple*
City = namedtuple(‘City’,‘name country population coordinates’)
tokyo = City(‘tokyo’,‘JP’,36.933,(35.689722,139.691667))
tokyo ====》 City(name=‘tokyo’, country=‘JP’, population=36.933, coordinates=(35.689722, 139.691667))
列表 元组 字符串都是支持切片操作的。
python默认序列是支持+和操作的。通常+号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,python会新建一个包含同样类型数据的序列来作为拼接的结果。+和都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列。

list.sort方法和内置函数sorted

list.sort方法会就地排序列表,也就是说不会把原列表复制一份,这也是这个方法的返回值为None的原因。
sorted内置函数,它会新建一个列表作为返回值,这个方法接收任何形式的可迭代对象作为参数。甚至包括不可变序列或生成器。而不管sorted接收的是怎样的参数,它最后都会返回一个列表。
不管list。sort方法还是sorted函数,都有两个可选的关键字参数: reverse 和 key,可选参数key还可以在内置函数min()和max()中起作用。

用bisect来管理已排序的序列

bisect模块包含两个主要函数,bisect和insort,这两个函数都利用二分查找算法来在有序序列中查找或插入元素
实例:
import bisect
import sys

HAYSTACK=[1,4,5,6,8,12,15,20,21,23,23,26,29,30]
NEEDLES=[0,1,2,5,8,10,22,23,29,30,31]
ROW_FMT=’{0:2d}@{1:2d} {2}{0:<2d}’

def demo(bisect_fn):
for needle in reversed(NEEDLES):
position = bisect_fn(HAYSTACK,needle) // 用特定的bisect函数来计算元素应该出现的位置
offset = position*’ |’ // 利用该位置来计算出需要几个分隔符号
print(ROW_FMT.format(needle,position,offset)) // 把元素和其应该出现的位置打印出来

if name == ‘main’:

if sys.argv[-1] == 'left': // 根据命令上最后一个参数来选用bisect函数
    bisect_fn = bisect.bisect_left

else:
    bisect_fn = bisect.bisect
print('DEMO:',bisect_fn.__name__) // 把选定的函数在抬头打印出来
print('haystack  ->',' '.join('%2d'%n for n in HAYSTACK) )
demo(bisect_fn)

bisect可以用来建立一个用数字作为索引的查询表格。
bisect.insort(seq,item)把变量item插入到序列seq中,并能保持seq的升序排序。

数组(array.array)

如果我们需要一个只包含数字的列表,那么arrary.arrary比list更高效。数组支持所有跟可变序列相关的操作,比如.pop .insert和.extend,另外,数组还提供从文件读取和存入文件的更快的方法。如:.formbytes和.tofile。
arrary(b’ ')创建出的数组只能存放一个字节大小的整数(-128-127)

NumPy和SciPy

Numpy提供高阶数组,SciPy提供矩阵操作,SciPy是基于NumPy的另一个库,它提供了很多跟科学计算有关的算法。专为线性代数,数值积分和统计学而设计。

双向队列和其他形式的队列

collections.deque类(双向队列)是一个线程安全,可以快速从两端添加或者删除元素的数据类型。
双向队列实现了大部分列表所拥有的方法,也有一些额外的符合自身设计的方法,比如说popleft和rotate。但是为了实现这些方法,双向队列也付出了一些代价,从队列中间删除元素的操作要慢一些,因为它只对在头尾的操作进行了优化。
append和popleft都是原子操作,也就是说deque可以在多线程程序总安全地当作先进先出的队列使用,而使用这不需要担心资源锁的问题。
除了deque之外,还有其他python标准库也有对队列的实现:
queue: 提供了同步(线程安全)类Queue,lifoQueue和PriortyQueue,不同的线程利用这些数据类型来交换信息。这三个类的构造方法都有一个可选参数maxsize,限定队列的大小。
mutiprocessing: 这个包实现了自己的Queue,它跟queue.Queue类似,是设计给进程间通信用的。
asynico: 为异步编程里的任务管理提供了专门的便利。
heapq: heapq没有队列类,而是提供了heappush和heappop方法。让用户可以把可变序列当作堆队列或者优先队列来使用。
list.sort sorted max和min函数的key参数是很好的设计。

字典和集合

泛映射类型

collections.abc模块中有Mapping 和MutaleMapping这两个抽象基类.他们的作用为dict和其他类似的类型定义形式接口然而,非抽象映射类型一般不会直接继承这些抽象基类,他们直接对dict或者collections.UserDict进行扩展,这些抽象基类的主要作用是作为形式化的文档,他们可以跟isinstance一起被用来判定某个数据是不是广义上的映射类型.
标准库里的所有映射类型都是理由dict来实现的,因此它们有个共同的限制,即只有可散列的数据类型才能用作这些映射里的键(只有键有这个要求,值并不需要是可散列的数据类型)
标准库里collections模块中,除了defaultdict之外的不同映射类型.
collections.OrderedDict 这个类型在添加键的时候会保持顺序,因此键的迭代次序总是一致的.
collections.ChainMap 这个类型可以容纳数个不同的映射对象,然后在进行键查找操作的时候,这些对象会被当做一个整体被逐个查找,直到键被找到为止.
collections.Counter: 这个映射类型会给键准备一个整数计数器.每次更新一个键的时候都会增加这个计数器.所以这个类型用来给可散列表对象计数,或者当多重集来用.
collections.UserDice: 这个类其实就是把标准dict用纯python实现了一遍,

集合

集合的本质是许多唯一对象的聚集,因此集合可以用于去重.
集合是实现了很多基础的中辍运算符.a|b返回的是他们的合集,a&b得到的是交集,a-b的到的是差集(存在于a但不存在与b的元素).a^b是:.对称差集 只在a或只在b的元素.
python3里面,除了空集,集合的字符串表示形式总是以{…}的形式出现
想求4个聚合类型a,b,c和d的合集,可以用a.union(b,c,d),这里a必须是有set,但是b c d则可以是任何类型的可迭代对象.
在python3中,.keys() .items() .values()方法返回的都是字典视图,也就是说这些方法返回的值更像集合.
集合总结:
集合里的元素必须是可散列的
集合很消耗内存
可以很高效的判断元素是否存储于集合.
元素的次序取决于被添加到集合里面的次序
往集合里面添加元素,可能会改变集合里已有元素的次序.
a_set = {1,2,3,4,5}
{1,2,3}.issubset(a_set) 检测一个集合是否是另一个集合的子集或父集

函数

关键字参数必须位于位置参数之后.

生成器和迭代器

迭代器是一种特殊对象,它可以在诸如for循环之类的上下文中向python解释器输送对象,大部分能接受列表之类的对象的方法也都可以接受任何可迭代对象.比如:min max sum等内置方法以及list tuple等类型构造器
生成器是构造新的可迭代对象的一种简单方式. 一般的函数执行之后只会返回单个值,而生成器则是以延迟的方式返回一个值序列,即每返回一个值之后暂停,直到下一个值被请求时再继续.要创建一个生成器,只需将函数中的return替换为yeild即可
另一种更简洁的构造生成器的方法是使用生成器表达式.器创建方式为,把列表推导式两端的方括号改为圆括号. 生成器表达式也可以取代列表推导式,作为函数参数

itertools模块

标准库itertools模块中有一组用于许多常见数据算法的生成器.它根据函数的返回值对序列中的连续元素进行分组.

你可能感兴趣的:(流畅的python第一章 数据模型 第二章序列构成的数组 第三章字典和集合)