collections
collections是Python内建的一个集合模块,提供了许多有用的集合类和方法。
可以把它理解为一个容器,里面提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。
namedtuple() : 创建一个命名元组子类的工厂函数
deque : 高效增删改双向列表,类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
defaultdict : 当字典查询时,为key不存在提供一个默认值。
OrderedDict : 有序词典,就是记住了插入顺序
Counter : 计数功能
namedtuple() 命名元组
namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
参数
- typename : 命名的名字,返回一个新的元组子类,名为 typename
- field_names : 可以是一个[‘x’, ‘y’]这样的序列,也可以是’x, y’或者’x y’
- rename : python3.1添加,如果 rename 为真, 无效域名会自动转换成位置名。比如 [‘abc’, ‘def’, ‘ghi’, ‘abc’] 转换成 [‘abc’, ‘_1’, ‘ghi’, ‘_3’] , 消除关键词 def 和重复域名 abc 。
- defaults : python3.7添加, defaults 可以为 None 或者是一个默认值的 iterable(可迭代对象)。如果一个默认值域必须跟其他没有默认值的域在一起出现, defaults 就应用到最右边的参数。比如如果域名 [‘x’, ‘y’, ‘z’] 和默认值 (1, 2) ,那么 x 就必须指定一个参数值 ,y 默认值 1 , z 默认值 2 。
- module : python3.6添加,如果 module 值有定义,命名元组的 __module__属性值就被设置
namedtuple使用
import collections
# 创建对象 我们定义了一个Point类型的包含x,y两个值的增强元祖类型
PointA = collections.namedtuple('Point', ['x', 'y'])
p = PointA(10, y=20) # 可以使用关键字参数和位置参数初始化namedtuple
#注意这个p类型既是我们定义的Point也是tuple,而元祖是不可使用_make 赋值和_replace 更改值的
print(p) # 直接打印 Point(x=10, y=20) 也可以获取单个内容 p.x p.y
p_list = [PointA(i, y=-i) for i in range(5)] #也可迭代生成一个list
print(p_list) # [Point(x=0, y=0), Point(x=1, y=-1), Point(x=2, y=-2), Point(x=3, y=-3), Point(x=4, y=-4)]
print(len(p_list)) # 获取长度 5
print(p_list[0]) # 根据下标取 Point(x=0, y=0)
from random import choiceprint(choice(p_list)) # 随机取一个
print(p_list[:3]) # 取前三个
print(p_list[0::2]) # 取第0个 然后每隔2个取一个
这是一些对list操作的特殊方法,是Python 自有的对序列数据类型的一些操作
[print(p_item) for p_item in reversed(p_list)] # 反向排序输出print(PointA("A", "B") in p_list)
print(PointA(0, 0) in p_list)
for p_item in sorted(p_list, key=lambda x: x.y): #匿名函数 参数:算式表达式# 根据每个元素的y值排序,也可以写个函数自己定义一个,返回值根据返回值默认从小到大排print(p_item)
sorted() 函数对所有可迭代的对象进行排序操作。
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
sorted(iterable, key=None, reverse=False)
参数说明:
- iterable -- 可迭代对象。
- key -- 用来进行比较的元素,可以是一个函数,也可以是一个类,也可以是其他的处理方法。只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
返回值:
返回重新排序的列表。
类中使用namedtuple
在类中使用 namedtuple 如果需要对这个类实例化的对象所有的对[]操作都操作到 类中定义的namedtuple 对象上,只需要在类中实现 __len__方法和__getitem__方法就好了
PointA = collections.namedtuple('Point', ['x', 'y'])
class PointList:def __init__(self):self._point = [PointA(i, y=-i) for i in range(5)]def __len__(self): #上面列表推导式的 len函数本质就是这个len的实现return len(self._point)def __getitem__(self, position): #上面后续其他对元素的操作 依赖于__getitem__# 也就是对这个类实例化对象的对[]的操作都给了self._point列表# 如[x]按下标取, random.choice,切片,迭代,sorted排序等return self._point[position]
point_list=PointList()
print(len(point_list))
print(collections.Counter(point_list))
优点是可以更加方便地利用 Python 的标准库,比如 random.choice 函
数,从而不用重新发明轮子。这都是由 __getitem__ 方法提供的
好,我们这时候想打乱一下这个序列,我们知道有 random.shuffle 函
数可用
from random import shuffle
shuffle(point_list)
他会报错:TypeError: 'PointList' object does not support item assignment
('PointList' 对象不支持为元素赋值)。这个问题的原因是,shuffle 函数要调换集合中元素的位置,而 PointList只实现
了不可变的序列协议。可变的序列还必须提供 __setitem__ 方法。
class PointList:def __init__(self):self._point = [PointA(i, y=-i) for i in range(5)]def __len__(self): #上面列表推导式的 len函数本质就是这个len的实现return len(self._point)def __getitem__(self, position): #上面后续其他对元素的操作 依赖于__getitem__# 也就是对这个类实例化对象的对[]的操作都给了self._point列表# 如[x]按下标取, random.choice,切片,迭代,sorted排序等return self._point[position]def __setitem__(self, key, value):self._point[key]=value
point_list=PointList()
print(len(point_list))
# print(collections.Counter(point_list))from random import shuffle
shuffle(point_list)
print(point_list[:3])
定义__setitem__函数,它的参数为 self、key和 value。我们对self的_point根据key取到的元素改value。现在可以打乱 point_list了,因为 PointList实现了可变序列协议所需的方法。
当然我们也可以定义一个方法,然后利用python动态语言的猴子特性,可以在外面直接赋值给PointList类的__setitem__属性
def set_point(p, key, value): p._point[key] = value
PointList.__setitem__ = set_point
这里的关键是point_list对象有一个名为 _point的属性,而且 _point的值必须是可变序列。然后,我们实现特殊方法 __setitem__,从而把它依附到 PointList类上。