【python学习笔记】python-collections学习笔记
本博客参考了:
Python中collections模块
collections --- 容器数据类型
这个模块实现了特定目标的容器,以提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。
- ChainMap:类似字典(dict)的容器类,将多个映射集合到一个视图里面
- Counter:字典的子类,提供了可哈希对象的计数功能
- deque:类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
- defaultdict:字典的子类,提供了一个工厂函数,为字典查询提供一个默认值
- namedtuple():创建命名元组子类的工厂函数
- OrderedDict:字典的子类,保存了他们被添加的顺序
- UserDict:封装了字典对象,简化了字典子类化
- UserList:封装了列表对象,简化了列表子类化
- UserString:封装了列表对象,简化了字符串子类化
ChainMap
一个 ChainMap 类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。
它通常比创建一个新字典和多次调用 update() 要快很多。
collections.ChainMap(*maps)
如果没有 maps 被指定,就提供一个默认的空字典,这样一个新链至少有一个映射。
from collections import ChainMap
d1 = {'apple':1,'banana':2}
d2 = {'orange':2,'apple':3,'pike':1}
combined_d = ChainMap(d1,d2)
reverse_combind_d = ChainMap(d2,d1)
print(combined_d)
print(reverse_combind_d)
'''
逐项输出时,从第二个dict的第一项开始输出;
当输出到两个dict都有的key,输出且只输出第一个dict的value
'''
for k,v in combined_d.items():
print(k,v)
print('------------------')
for k,v in reverse_combind_d.items():
print(k,v)
ChainMap({'apple': 1, 'banana': 2}, {'orange': 2, 'apple': 3, 'pike': 1})
ChainMap({'orange': 2, 'apple': 3, 'pike': 1}, {'apple': 1, 'banana': 2})
orange 2
apple 1
pike 1
banana 2
------------------
apple 3
banana 2
orange 2
pike 1
def collection_test2():
import builtins
from collections import ChainMap
a = {"name": "leng"}
b = {"age": 24}
c = {"wife": "qian"}
pylookup = ChainMap(a,b,c)
print(pylookup)
print(pylookup['age'],pylookup.maps)
#upadte()只能更新第一个dict
pylookup.update({"age": 25})
print(pylookup)
pylookup.update({"age": 28})
print(pylookup)
#更新各自代表的dict
b['age'] = 26
c['wife'] = "zheng"
print(pylookup)
print(type(pylookup.maps))
#更新指定dict
pylookup.maps[0]['age']=20
pylookup.maps[1]['age']=22
print(pylookup)
print("-----------")
d = {"name": "leng"}
e = {"name":"123"}
cm = ChainMap(d,e)
print(cm)
print(cm['name'])
collection_test2()
ChainMap({'name': 'leng'}, {'age': 24}, {'wife': 'qian'})
24 [{'name': 'leng'}, {'age': 24}, {'wife': 'qian'}]
ChainMap({'name': 'leng', 'age': 25}, {'age': 24}, {'wife': 'qian'})
ChainMap({'name': 'leng', 'age': 28}, {'age': 24}, {'wife': 'qian'})
ChainMap({'name': 'leng', 'age': 28}, {'age': 26}, {'wife': 'zheng'})
<class 'list'>
ChainMap({'name': 'leng', 'age': 20}, {'age': 22}, {'wife': 'zheng'})
-----------
ChainMap({'name': 'leng'}, {'name': '123'})
leng
Counter
Counter是一个dict子类,主要是用来对你访问的对象的频率进行计数,是一个计数器工具提供快速和方便的计数。
常用方法:
- elements():返回一个迭代器,每个元素重复计算的个数,如果一个元素的计数小于1,就会被忽略。
- most_common([n]):返回一个列表,提供n个访问频率最高的元素和计数
- subtract([iterable-or-mapping]):从迭代对象中减去元素,输入输出可以是0或者负数
- update([iterable-or-mapping]):从迭代对象计数元素或者从另一个 映射对象 (或计数器) 添加。
from collections import Counter
# 统计字符出现的次数
print(Counter('hello world'))
# 统计单词数
c = Counter('hello world hello world hello nihao'.split())
print(c)
cnt = Counter()
for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
cnt[word] += 1
print(cnt)
# 获取指定对象的访问次数,也可以使用get()方法
print(c['hello'])
print(c.get('hello'))
# 查看元素
print(list(c.elements()))
print(c.elements())
# 追加对象,或者使用c.update(d)
c = Counter('hello world hello world hello nihao'.split())
d = Counter('hello world'.split())
print(c)
print(d)
print(c + d)
c.update(d)
print(c)
#减少对象,或者使用c.subtract(d)
c = Counter('hello world hello world hello nihao'.split())
print(c - d)
c.subtract(d)
print(c)
# 清除
c.clear()
print(c)
Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
Counter({'hello': 3, 'world': 2, 'nihao': 1})
Counter({'blue': 3, 'red': 2, 'green': 1})
3
3
['hello', 'hello', 'hello', 'world', 'world', 'nihao']
<itertools.chain object at 0x000001FC132A38C8>
Counter({'hello': 3, 'world': 2, 'nihao': 1})
Counter({'hello': 1, 'world': 1})
Counter({'hello': 4, 'world': 3, 'nihao': 1})
Counter({'hello': 4, 'world': 3, 'nihao': 1})
Counter({'hello': 2, 'world': 1, 'nihao': 1})
Counter({'hello': 2, 'world': 1, 'nihao': 1})
Counter()
deque
collections.deque
返回一个新的双向队列对象,从左到右初始化(用方法 append()) ,从 iterable (迭代对象) 数据创建。如果 iterable 没有指定,新队列为空。
Deque队列是由栈或者queue队列生成的。Deque支持线程安全,对于从两端添加(append)或者弹出(pop),复杂度O(1)。
虽然list对象也支持类似操作,但是这里优化了定长操作(pop(0)、insert(0,v))的开销。
如果 maxlen 没有指定或者是 None ,deques 可以增长到任意长度。否则,deque就限定到指定最大长度。
一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。
支持的方法:
- append(x):添加x到右端
- appendleft(x):添加x到左端
- clear():清楚所有元素,长度变为0
- copy():创建一份浅拷贝
- count(x):计算队列中个数等于x的元素
- extend(iterable):在队列右侧添加iterable中的元素
- extendleft(iterable):在队列左侧添加iterable中的元素,注:在左侧添加时,iterable参数的顺序将会反过来添加
- index(x[,start[,stop]]):返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。返回第一个匹配项,如果未找到则引发 ValueError。
- insert(i,x):在位置 i 插入 x 。注:如果插入会导致一个限长deque超出长度 maxlen 的话,就升起一个 IndexError 。
- pop():移除最右侧的元素
- popleft():移除最左侧的元素
- remove(value):移去找到的第一个 value。没有抛出ValueError
- reverse():将deque逆序排列。返回 None 。
- maxlen:队列的最大长度,没有限定则为None。
from collections import deque
d = deque(maxlen=20)
print(d)
d.extend('python')
print(d)
for elem in d:
print(elem.upper())
deque([], maxlen=20)
deque(['p', 'y', 't', 'h', 'o', 'n'], maxlen=20)
P
Y
T
H
O
N
d.append('e')
print(d)
x = 'java'
d.appendleft(x)
print(d)
deque(['p', 'y', 't', 'h', 'o', 'n', 'e'], maxlen=20)
deque(['java', 'p', 'y', 't', 'h', 'o', 'n', 'e'], maxlen=20)
print(d.count('p'))
1
d.extendleft('cpp')
print(d)
deque(['p', 'p', 'c', 'java', 'p', 'y', 't', 'h', 'o', 'n', 'e'], maxlen=20)
x = 'java'
print(d.index(x))
print(d.index('p'))
3
0
d.insert(3,'a')
print(d)
deque(['p', 'p', 'c', 'a', 'java', 'p', 'y', 't', 'h', 'o', 'n', 'e'], maxlen=20)
d.pop()
print(d)
d.popleft()
print(d)
deque(['p', 'p', 'c', 'a', 'java', 'p', 'y', 't', 'h', 'o', 'n'], maxlen=20)
deque(['p', 'c', 'a', 'java', 'p', 'y', 't', 'h', 'o', 'n'], maxlen=20)
value = 'java'
d.remove(value)
print(d)
d.reverse()
print(d)
d.clear()
print(d)
deque(['p', 'c', 'a', 'p', 'y', 't', 'h', 'o', 'n'], maxlen=20)
deque(['n', 'o', 'h', 't', 'y', 'p', 'a', 'c', 'p'], maxlen=20)
deque([], maxlen=20)
defaultdict
返回一个新的类似字典的对象。
defaultdict 是内置 dict 类的子类。它重载了一个方法并添加了一个可写的实例变量。
其余的功能与 dict 类相同,此处不再重复说明。
本对象包含一个名为 default_factory 的属性,构造时,第一个参数用于为该属性提供初始值,默认为 None。
所有其他参数(包括关键字参数)都相当于传递给 dict 的构造函数。
from collections import defaultdict
d = defaultdict()
print(d)
#使用list做default_factory
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
#直接添加,如果要加value在[]后加.append(value)即可
d['hello']
print(d)
print(sorted(d.items()))
for k, v in s:
d[k].append(v)
print(sorted(d.items()))
defaultdict(None, {})
defaultdict(<class 'list'>, {'hello': []})
[('hello', [])]
[('blue', [2, 4]), ('hello', []), ('red', [1]), ('yellow', [1, 3])]
#设置 default_factory 为 int,使 defaultdict 用于计数
s = 'mississippi'
d = defaultdict(int)
for k in s:
d[k] += 1
print(sorted(d.items()))
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]
namedtuple()
命名元组赋予每个位置一个含义,提供可读性和自文档性。
它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的。
(看例子有点java的实体类的感觉)
from collections import namedtuple
Person = namedtuple('Person', ['age', 'height', 'name'])
Human = namedtuple('Human', 'age, height, name')
student = namedtuple('student', 'age height name')
tom = Person(30,178,'Tom')
jack = Human(20,179,'Jack')
print(jack)
print(tom)
print(tom.age)
print(jack.height)
Human(age=20, height=179, name='Jack')
Person(age=30, height=178, name='Tom')
30
179
OrderedDict
有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。
由于内置的 dict 类获得了记住插入顺序的能力(在 Python 3.7 中保证了这种新行为),它们变得不那么重要了。
一些与 dict 的不同仍然存在:
- 常规的 dict 被设计为非常擅长映射操作。 跟踪插入顺序是次要的。
- OrderedDict 旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。
- 算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。
- 对于 OrderedDict ,相等操作检查匹配顺序。
- OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。
- OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。
- Python 3.8之前, dict 缺少 reversed() 方法。
from collections import OrderedDict
od = OrderedDict()
od['country'] = '1'
od['sex'] = '0'
od['age'] = '34'
print(od)
OrderedDict([('country', '1'), ('sex', '0'), ('age', '34')])
od.move_to_end('country')
print(od)
OrderedDict([('sex', '0'), ('age', '34'), ('country', '1')])
UserDict
是用作字典对象的外包装。对这个类的需求已部分由直接创建 dict 的子类的功能所替代;
不过,这个类处理起来更容易,因为底层的字典可以作为属性来访问。
UserList
封装了列表对象。它是一个有用的基础类,对于你想自定义的类似列表的类,可以继承和覆盖现有的方法,也可以添加新的方法。
这样我们可以对列表添加新的行为。
对这个类的需求已部分由直接创建 list 的子类的功能所替代;
不过,这个类处理起来更容易,因为底层的列表可以作为属性来访问。
UserString
类是用作字符串对象的外包装。对这个类的需求已部分由直接创建 str 的子类的功能所替代;
不过,这个类处理起来更容易,因为底层的字符串可以作为属性来访问。