Python学习:collections模块

简介

collections模块实现了一些特定目标的容器,以提供对Python内建的容器dict、list、set与tuple的替代选择。具体实现的容器包括:

序号容器名称容器描述
1namedtuple创建命名元组子类的工厂函数
2deque类似list的容器,实现在list两端快速的append和pop操作
3ChainMap类似dict的容器类,将多个映射集合到一个视图中
4Counter字典的子类,提供可哈希对象的计数功能
5OrderedDict字典的子类,保存元素被添加的顺序
6defaultdict字典的子类,提供一个工厂函数,为字典查询提供一个默认值
7UserDict封装了字典对象,简化了字典子类化
8UserList封装了列表对象,简化了列表子类化
9UserString封装了字符串对象,简化了字符串子类化

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
#以字符串元组的方式列出命名元组的域名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值