Collections
Python的集合(collections)模块,为很多用其他方法很难实现的场景提供了解决方案。
通俗说法:Python内置的数据类型和方法,collections模块在这些内置类型的基础提供了额外的高性能数据类型,比如基础的字典是不支持顺序的,collections模块的OrderedDict类构建的字典可以支持顺序,collections模块的这些扩展的类用处非常大,熟练掌握该模块,可以大大简化Python代码,提高Python代码逼格和效率,高手入门必备。
用collections.__all__查看所有的子类,一共包含9个.这个模块实现了特定目标的容器,以提供Python标准内建容器dict , list , set , 和tuple 的替代选择。
import collections
print(collections.__all__)
['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
'UserString', 'Counter', 'OrderedDict', 'ChainMap']
namedtuple | 创建命名元组子类的工厂函数,生成可以使用名字来访问元素内容的tuple子类 |
---|---|
deque | 类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop) |
ChainMap | 类似字典(dict)的容器类,将多个映射集合到一个视图里面 |
Counter | 字典的子类,提供了可哈希对象的计数功能 |
OrderedDict | 字典的子类,保存了他们被添加的顺序,有序字典 |
defaultdict | 字典的子类,提供了一个工厂函数,为字典查询提供一个默认值 |
UserDict | 封装了字典对象,简化了字典子类化 |
UserList | 封装了列表对象,简化了列表子类化 |
UserString | 封装了字符串对象,简化了字符串子类化(中文版翻译有误) |
1 计数器-Counter
一个计数器工具提供快速和方便的计数,Counter是一个dict的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数
L = ['red', 'blue', 'red', 'green', 'blue', 'blue']
Counter(L)
Counter({'red': 2, 'blue': 3, 'green': 1}
元素从一个iterable 被计数或从其他的mapping (or counter)初始化:
Counter('gallahad')
# Counter({'g': 1, 'a': 3, 'l': 2, 'h': 1, 'd': 1})
1.1、elements()
描述:返回一个迭代器,其中每个元素将重复出现计数值所指定次。 元素会按首次出现的顺序返回。 如果一个元素的计数值小于1,elements() 将会忽略它。
c = Counter(a=4, b=2, c=0, d=-2)
list(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
c = Counter(a=4, b=2, c=0, d=5)
list(c.elements())
['a', 'a', 'a', 'a', 'b', 'b', 'd', 'd', 'd', 'd', 'd']
1.2、most_common()
返回一个列表,其中包含n个最常见的元素及出现次数,按常见程度由高到低排序。 如果 n 被省略或为None,most_common() 将返回计数器中的所有元素,计数值相等的元素按首次出现的顺序排序,经常用来计算top词频的词语。
Counter('abracadabra').most_common(3)
[('a', 5), ('b', 2), ('r', 2)]
Counter('abracadabra').most_common(5)
[('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]
1.3、subtract()
从迭代对象或映射对象减去元素。像dict.update() 但是是减去,而不是替换。输入和输出都可以是0或者负数。
#减去一个abcd
str0 = Counter('aabbccdde')
str0
Counter({'a': 2, 'b': 2, 'c': 2, 'd': 2, 'e': 1})
str0.subtract('abcd')
str0
Counter({'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1}
2、双向队列-deque
我们都知道queue是队列,deque也是队列,不过稍稍特殊一些,是双端队列。对于queue来说,只允许在队尾插入元素,在队首弹出元素。而deque既然称为双端队列,那么说明它的队首和队尾都支持元素的插入和弹出。相比于普通的队列,要更加灵活一些。在日常的使用当中,真正用到双端队列的算法其实不太多。大多数情况下我们使用deque主要有两个原因,第一个原因是deque收到GIL的管理,它是线程安全的。而list则没有GIL锁,因此不是线程安全的。也就是说在并发场景下,list可能会导致一致性问题,而deque不会。另一个原因是deque支持固定长度,当长度满了之后,当我们继续append时,它会自动弹出最早插入的数据。
append(x):添加 x 到右端。
appendleft(x):添加 x 到左端。
clear():移除所有元素,使其长度为0.
copy():创建一份浅拷贝。3.5 新版功能.
count(x):计算deque中个数等于 x 的元素。3.2 新版功能.
extend(iterable):扩展deque的右侧,通过添加iterable参数中的元素。
extendleft(iterable):扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加。
index(x[, start[, stop]]):返回第 x 个元素(从 start 开始计算,在 stop 之前)。返回第一个匹配,如果没找到的话,升起 ValueError 。3.5 新版功能.
insert(i, x):在位置 i 插入 x 。如果插入会导致一个限长deque超出长度 maxlen 的话,就升起一个 IndexError 。3.5 新版功能.
pop():移去并且返回一个元素,deque最右侧的那一个。如果没有元素的话,就升起 IndexError 索引错误。
popleft():移去并且返回一个元素,deque最左侧的那一个。如果没有元素的话,就升起 IndexError 索引错误。
remove(value):移去找到的第一个 value。 如果没有的话就升起 ValueError 。
reverse():将deque逆序排列。返回 None 。3.2 新版功能.
rotate(n=1):向右循环移动 n 步。 如果 n 是负数,就向左循环。如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。
Deque对象同样提供了一个只读属性:
maxlen:Deque的最大尺寸,如果没有限定的话就是 None 。
2.1、append()
添加 x 到右端。
d = deque('ghi')
d.append('j')
d
deque(['g', 'h', 'i', 'j'])
2.2、appendleft()
添加 x 到左端。
d.appendleft('f')
d
deque(['f', 'g', 'h', 'i', 'j'])
2.3、clear()
移除所有元素,使其长度为0.
d = deque('ghi')
d.clear()
d
deque([])
2.4、copy()
创建一份浅拷贝。
d = deque('xiaoweuge')
y = d.copy()
print(y)
deque(['x', 'i', 'a', 'o', 'w', 'e', 'u', 'g', 'e'])
2.5、count()
计算 deque 中元素等于 x 的个数。
d = deque('xiaoweuge-shuai')
d.count('a')
2
2.6、extend()
扩展deque的右侧,通过添加iterable参数中的元素。
a = deque('abc')
b = deque('cd')
a.extend(b)
a
deque(['a', 'b', 'c', 'c', 'd'])
#与append 的区别
a = deque('abc')
b = deque('cd')
a.append(b)
deque(['a', 'b', 'c', deque(['c', 'd'])])
2.7、extendleft()
扩展deque的左侧,通过添加iterable参数中的元素。注意,左添加时,在结果中iterable参数中的顺序将被反过来添加。
a = deque('abc')
b = deque('cd')
a.extendleft(b)
a
deque(['d', 'c', 'a', 'b', 'c'])
2.8、index()
返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)。 返回第一个匹配项,如果未找到则引发 ValueError。
d = deque('xiaoweuge')
d.index('w')
4
2.9、insert()
在位置 i 插入 x 。
如果插入会导致一个限长 deque 超出长度 maxlen 的话,就引发一个 IndexError。
a = deque('abc')
a.insert(1,'X')
deque(['a', 'X', 'b', 'c'])
2.10、pop()
移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError。
d.pop()
'j'
2.11、popleft()
移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError。
d.popleft()
'f'
2.12、remove(value)
移除找到的第一个 value。 如果没有的话就引发 ValueError。
a = deque('abca')
a.remove('a')
a
deque(['b', 'c', 'a'])
2.13、reverse()
将deque逆序排列。返回 None 。
#逆序排列
d = deque('ghi') # 创建一个deque
list(reversed(d))
['i', 'h', 'g']
deque(reversed(d))
deque(['i', 'h', 'g'])
2.14、rotate(n=1)
向右循环移动 n 步。 如果 n 是负数,就向左循环。
如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。
# 向右边挤一挤
d = deque('ghijkl')
d.rotate(1)
d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
# 向左边挤一挤
d.rotate(-1)
d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
#看一个更明显的
x = deque('12345')
x
deque(['1', '2', '3', '4', '5'])
x.rotate()
x
deque(['5', '1', '2', '3', '4'])
d = deque(['12','av','cd'])
d.rotate(1)
deque(['cd', '12', 'av'
2.15、maxlen
Deque的最大尺寸,如果没有限定的话就是 None 。
from collections import deque
d=deque(maxlen=10)
for i in range(20):
d.append(i)
d
deque([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
3、有序字典-OrderedDict
有序词典就像常规词典一样,但有一些与排序操作相关的额外功能,popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。move_to_end() 方法,可以有效地将元素移动到任一端。
有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。由于内置的 dict 类获得了记住插入顺序的能力(在 Python 3.7 中保证了这种新行为),它们变得不那么重要了。
一些与 dict 的不同仍然存在:
- 常规的 dict 被设计为非常擅长映射操作。 跟踪插入顺序是次要的。
- OrderedDict 旨在擅长重新排序操作。 空间效率、迭代速度和更新操作的性能是次要的。
- 算法上, OrderedDict 可以比 dict 更好地处理频繁的重新排序操作。 这使其适用于跟踪最近的访问(例如在 LRU cache 中)。
- 对于 OrderedDict ,相等操作检查匹配顺序。
- OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。
- OrderedDict 类有一个 move_to_end() 方法,可以有效地将元素移动到任一端。
- Python 3.8之前, dict 缺少 reversed() 方法。
传统字典方法 | OrderedDict方法 | 差异 |
---|---|---|
clear | clear | |
copy | copy | |
fromkeys | fromkeys | |
get | get | |
items | items | |
keys | keys | |
pop | pop | |
popitem | popitem | OrderedDict 类的 popitem() 方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。 |
setdefault | setdefault | |
update | update | |
values | values | |
move_to_end | 可以有效地将元素移动到任一端。 |
3.1 popitem
语法:popitem(last=True)
功能:有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。
from collections import OrderedDict
d = OrderedDict.fromkeys('abcde')
d.popitem()
('e', None)
d
OrderedDict([('a', None), ('b', None), ('c', None), ('d', None)])
#last=False时,弹出第一个
d = OrderedDict.fromkeys('abcde')
''.join(d.keys())
'abcde'
d.popitem(last=False)
''.join(d.keys())
'bcde'
3.2 move_to_end
from collections import OrderedDict
d = OrderedDict.fromkeys('abcde')
d.move_to_end('b')
''.join(d.keys())
'acdeb'
d
OrderedDict([('a', None), ('c', None), ('d', None), ('e', None), ('b', None)])
d.move_to_end('b', last=False)
''.join(d.keys())
'bacde'
3.3 reversed()
相对于通常的映射方法,有序字典还另外提供了逆序迭代的支持,通过reversed() 。
d = OrderedDict.fromkeys('abcde')
list(reversed(d))
['e', 'd', 'c', 'b', 'a']
4、可命名元组-namedtuple
参数
collections.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__属性值就被设置。
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
# p.x = 1,p.y = 2
# p._fields = ('x', 'y')
4.1 _make(iterable)
t = [14, 55]
Point._make(t) # Point(x=11, y=3)
4.2 _asdict()
返回一个新的 dict ,它将字段名称映射到它们对应的值:
p = Point(x=11, y=22)
p._asdict()
OrderedDict([('x', 11), ('y', 22)])
4.3 _replace(**kwargs)
返回一个新的命名元组实例,并将指定域替换为新的值
p = Point(x=11, y=22)
p._replace(x=33)
Point(x=33, y=22)
标签:deque,None,Counter,OrderedDict,Python,元素,Collections,字典
From: https://www.cnblogs.com/jzYe/p/17201808.html