简介
collections模块实现了一些特定目标的容器,以提供对Python内建的容器dict、list、set与tuple的替代选择。具体实现的容器包括:
序号 | 容器名称 | 容器描述 |
---|---|---|
1 | namedtuple | 创建命名元组子类的工厂函数 |
2 | deque | 类似list的容器,实现在list两端快速的append和pop操作 |
3 | ChainMap | 类似dict的容器类,将多个映射集合到一个视图中 |
4 | Counter | 字典的子类,提供可哈希对象的计数功能 |
5 | OrderedDict | 字典的子类,保存元素被添加的顺序 |
6 | defaultdict | 字典的子类,提供一个工厂函数,为字典查询提供一个默认值 |
7 | UserDict | 封装了字典对象,简化了字典子类化 |
8 | UserList | 封装了列表对象,简化了列表子类化 |
9 | UserString | 封装了字符串对象,简化了字符串子类化 |
ChainMap
一个ChainMap类是为了将多个映射快速链接到一起,这样可以将其作为一个单元处理。
当有多个字典或者映射时,想将其合并为一个单独的映射,可以使用字典的update进行合并,但是这样做会新建一个数据结构,导致对原来字典进行更改时,合并的内容不会同步,使用ChainMap建立一个合并字典或者映射,并可同步的查询方法。
方法与属性
class collections.ChainMap(*maps)
#将多个字典,或者其他映射组合在一起,创建一个单独的可同步更新的视图。
#底层实现实际上是将多个字典存储在一个队列中,当进行字典的查找时,从队列依次查找,
#一旦查到,则立即返回,当进行字典的增加删除操作时,只会在队列中的第一个字典上进行增加删除操作
#ChainMap通过引用合并底层的各个字典或者映射,所以,如果一个底层字典或者映射被更新,则同步反应到ChainMap
maps
#一个可以更新的映射列表,是仅有的存储形态,可以被修改
new_child(m=None)
#返回一个新的ChainMap类,包含一个新的映射,后面跟随当前实例的全部映射
#该方法的实质是在底层存储列表的第一个元素之前,放入一个字典,默认放入空字典{}
parents
#属性返回一个新的 ChainMap 包含所有的当前实例的映射,除了第一个。这样可以在搜索的时候跳过第一个映射。
范例
import collections
a = {'a':'A', 'c':'C'}
b = {'b':'B', 'c':'D'}
m = collections.ChainMap(a, b)
print(m.maps) #[{'c': 'C', 'a': 'A'}, {'c': 'D', 'b': 'B'}]
print('c = {}\n'.format(m['c'])) #c = C
m.maps = list(reversed(m.maps))
print(m.maps) #[{'c': 'D', 'b': 'B'}, {'c': 'C', 'a': 'A'}]
print('c = {}\n'.format(m['c'])) #c = D
#ChainMap将多个字典存储在底层一个列表中,该列表可通过属性maps获取
#查找ChainMap中元素,查找的顺序就是属性maps指向的列表中的字典顺序
#而该底层列表是可更改的,因此可以改变maps指向的列表中的内容,以控制ChainMap的查找结果
Counter
Counter对象是一个计数器工具,能够快速方便地计数。比如:
>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
... cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})
类与方法
class collections.Counter([iterable-or-mapping])
#一个Counter是一个字典的子类,用于计数可哈希对象。
#Counter对象是一个集合,key是被计数的元素,value是该元素的计数值,计数值可以是任意整数,包括负数
#创建一个Counter对象的参数可以是迭代对象,或者字典或者映射,或者为空
#初始化的方式如下:
>>> c = Counter() # a new, empty counter
>>> c = Counter('gallahad') # a new counter from an iterable
>>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping
>>> c = Counter(cats=4, dogs=8) # a new counter from keyword args
elements()
#返回一个迭代器,其中每个元素将重复出现计数值所指定次。 元素会按首次出现的顺序返回。
#如果一个元素的计数值小于1,elements() 将会忽略它
most_common([n])
#返回一个列表,其中包含 n 个最常见的元素及出现次数,按常见程度由高到低排序
#如果 n 被省略或为 None,most_common() 将返回计数器中的所有元素
#计数值相等的元素按首次出现的顺序排序
subtract([iterable-or-mapping])
#从迭代对象或映射对象减去元素,如:
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
deque
deque对象是一个双向队列对象,deque队列是由栈,或者queue队列生成,deque是“double ended queue”的简称,deque支持线程安全,内存高效的两端append与pop操作。
方法与属性
class collections.deque([iterable[, maxlen]])
#返回一个新的双向队列对象,从iterable数据创建
#若参数maxlen没有指定,或者为None,则deque可以增长到任意长度,否则,限定到指定的最大长度
#一旦限定长度的deque满了,当新的元素加入,同样数量的元素就从另一端弹出
append(x)
#添加x到右端
appendleft(x)
#添加x到左端
clear()
#移除所有的元素,使得队列长度为0
copy()
#创建一份浅拷贝
count(x)
#计算队列中x的个数
extend(iterable)
#扩展队列的右端,添加iterable中的元素
extendleft(iterable)
#扩展队列的左端,添加iterable中的元素
index(x[, start[, stop]])
#返回第 x 个元素(从 start 开始计算,在 stop 之前)。返回第一个匹配,如果没找到的话,产生异常 ValueError
insert(i, x)
#在位置i插入x
#如果插入会导致一个限长deque超出长度 maxlen 的话,引起异常 IndexError
pop()
#移去并且返回一个元素,deque最右侧的那一个。如果没有元素的话,引起异常 IndexError
popleft()
#移去并且返回一个元素,deque最左侧的那一个。如果没有元素的话,引起异常 IndexError
remove(value)
#移去找到的第一个 value。 如果没有的话,产生异常 ValueError
reverse()
#将deque逆序排列
rotate(n=1)
#向右循环移动 n 步。 如果 n 是负数,就向左循环
#如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop())
#向左循环一步就等价于 d.append(d.popleft())
maxlen
#属性,deque的最大限制长度,如果没有限制,则返回None
#除了以上操作,deque 还支持迭代、封存、len(d)、reversed(d)、copy.copy(d)、copy.deepcopy(d)、成员检测运算符 in 以及下标引用例如通过 d[0] 访问首个元素等
defaultdict
defaultdict对象是一个类似于字典的对象,是内存dict类的子类,defaultdict重载了dict类的一个方法,添加了一个可写的实例变量,其余功能与dict类相同。
class collections.defaultdict([default_factory[, ...]])
#参数default_factory提供了一个初始值,默认为None,其他参数与dict构造器中的参数相同
#注意,default_factory可看成一个方法,比如list、int、set
__missing__(key)
#除了dict的操作方法,该方法是defaultdict的扩展
#如果default_factory为None,则查找的key不存在时,引起KeyError异常
#如果default_factory不为None,则该方法将会被调用,为key提供一个默认值
#该方法在查询key值失败时,被dict类的__getitem__方法调用,其返回值,或者引起的异常,都会被__getitem__方法传递
#该方法不会被__getitem__以外的其他方法调用
default_factory
#为defaultdict类的属性,被__missing__方法调用
范例
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
... d[k].append(v)
...
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
#当每个键第一次遇见时,它还没有在字典里面
#所以条目自动创建,通过 default_factory 方法,并返回一个空的 list
#list.append() 操作添加值到这个新的列表里
#当键再次被存取时,就正常操作list.append() 添加另一个值到列表中
#这个计数比它的等价方法 dict.setdefault() 要快速和简单
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
... d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]
#当一个字母首次遇到时,它就查询失败,所以 default_factory 调用 int() 来提供一个整数0作为默认值
#自增操作然后建立对每个字母的计数。
default_factory也可以是自定义的方法:
import collections
def default_factory():
return 'default value'
d = collections.defaultdict(default_factory, foo='bar')
print('d:', d)
print('foo =>', d['foo'])
print('bar =>', d['bar'])
#输出
#d: defaultdict(<function default_factory at 0x101921950>,{'foo': 'bar'})
#foo => bar
#bar => default value
namedtuple
命名元组赋予元组的每个位置一个名称,提供元组的可读性,可以替代任何普通的元组。命名元组具有通过名称获取值的能力,也可以通过索引获取值。
collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
#构造器返回一个元组子类,子类名称为typename
#通过子类的名称typename可创建命名元组的实例对象
#参数field_names表示域名,可以通过域名来获取属性值,当然也可以通过索引或迭代获取值
#参数field_names可以是字符串序列,如['x','y','z']
#也可以是纯字符串,逗号或者空格分隔,如'x y z','x, y, z'
#若参数rename为True,则无效的域名将自动转换为位置名,如域名为['abc', 'def', 'ghi', 'abc']
#将被转换为['abc', '_1', 'ghi', '_3'],消除关键词 def 和重复域名 abc
#参数defaults表示命名元组的默认值,可以为None,或者为一个可迭代对象iterable
#如果参数module有定义,则命名元组的属性__module__将被设置
#命名元组除了继承普通元组的方法,还支持另外的方法与属性,为了防止与命名元组可能的域名冲突,方法与属性都以下划线开始
classmethod somenamedtuple._make(iterable)
#类方法从存在的序列或迭代实例创建一个新实例
somenamedtuple._asdict()
#方法返回一个新的字典,将字段名称映射到对应的值
somenamedtuple._replace(**kwargs)
#返回一个新的命名元组实例,将指定的域的值替换为新的值
somenamedtuple._fields
#以字符串元组的方式列出命名元组的域名