Python 容器
目录
1 简介
Python 的内置模块 collections 提供了通用内置容器 dict, list, set, tuple 的替代方案。
Python2 和 Python3 在这个模块上具有一些区别, 所以后面的内容分为:
Python2和Python3都支持的容器类型Python3支持的容器类型
2 Python2 & Python3
2.1 Counter
Counter 提供计数器以支持方便快捷的计数。
一个例子:
>>> lst = [1, 2, 3, 4, 5, 6, 6, 6, 2, 1]
>>> Counter(lst)
Counter({6: 3, 1: 2, 2: 2, 3: 1, 4: 1, 5: 1})
初始化 Counter 对象:
>>> c = Counter() # 空的新容器 >>> c = Counter('abcdefg') # 通过一个可迭代对象初始化 >>> c = Counter({'red': 4, 'blue': 2}) # 通过一个映射对象初始化 >>> c = Counter(boy=30, girl=8) # 通过关键字参数初始化
和 dict 的一个不同:
# 访问不存在的键时, 不是引发 KeyError, 而是返回一个 0 计数 >>> c = Counter(['girl', 'boy']) >>> c Counter({'boy': 1, 'girl': 1}) >>> c['nogirl'] 0
2.1.1 方法
- elements()
返回计数器中的所有元素的 迭代器, 每个元素的重复次数和其计数相同。
>>> c = Counter(a=4, b=2, c=0, d=-2) >>> list(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
- most_common([n])
列出出现次数最多的
n个元素及其计数, 如果省略n, 便返回所有元素。>>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)]
- substract([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})
- update([iterable-or-mapping])
从一个 可迭代 对象或一个 映射 对象中加上元素计数。
>>> c = Counter(a=4, b=2, c=0, d=-2) >>> d = Counter(a=1, b=2, c=3, d=4) >>> c.update(d) >>> c Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2})
- 数学运算
>>> c = Counter(a=3, b=1) >>> d = Counter(a=1, b=2) >>> c + d # add two counters together: c[x] + d[x] Counter({'a': 4, 'b': 3}) >>> c - d # subtract (keeping only positive counts) Counter({'a': 2}) >>> c & d # intersection: min(c[x], d[x]) Counter({'a': 1, 'b': 1}) >>> c | d # union: max(c[x], d[x]) Counter({'a': 3, 'b': 2}) # Python3 还支持 >>> c = Counter(a=2, b=-4) >>> +c Counter({'a': 2}) >>> -c Counter({'b': 4})
2.2 deque
deque 是提供快速追加和两端弹出的类列表容器。
初始化 deque 对象:
# deque([iterable[, maxlen]]) --> deque object # param: iterable --> 可迭代对象 # param: maxlen --> 定义 deque 的最大长度 # 如果 maxlen 为 None, deque 可增长到任意长度 # 如果 maxlen 不为 None, 在 deque 达到最大长度时, 添加元素的同时从对端删除相同数量的元素 >>> d = deque([1,2,3,4,5,6,7,8,9], maxlen=10) >>> d.append(10) >>> d deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], maxlen=10) >>> d.append(11) >>> d deque([2, 3, 4, 5, 6, 7, 8, 9, 10, 11], maxlen=10)
2.2.1 方法
- append(x)
- 添加
x到右端 - appendleft(x)
- 添加
x到左端 - clear()
- 移除所有元素使
deque的长度为零 - copy()
- 创建一个
deque的浅表副本 - count(x)
- 获取等于
x的元素的个数 - extend(iterable)
- 使用可迭代对象的元素扩展
deque的右端 - extendleft(iterable)
- 使用可迭代对象的元素扩展
deque的左端 - index(x[, start[, stop]])
- (python3) 返回
deque中的x的位置(在索引开始处或索引停止之前)。如果未找到, 引发ValueError - insert(i, x)
- (python3) 在
i处插入x, 如果insert将导致deque大长度超出maxlen, 将会引发IndexError. - pop()
- 移除右端的一个元素, 如果
deque为空, 引发IndexError - popleft()
- 移除左端的一个元素, 如果
deque为空, 引发IndexError - remove(value)
- 移除第一个
value, 如果不存在引发ValueError - reversse()
- 翻转
deque并返回None - ronate(n=1)
根据指定的
step向右翻转deque. 如果n为负数, 便向左翻转。注:
n不是关键字参数
2.2.2 属性
- maxlen
- 只读属性, 返回
maxlen或None
2.3 defaultdict
defaultdict 是 dict 的一个子类, 覆盖了一个方法并添加了一个可写实例变量。
defaultdict 的第一个参数用来初始化 defaul_factory, 其余参数和 dict 相同。
覆盖的方法:
__missing__(key)这个方法受添加的可写实例变量
default_factory影响。如果
default_factory为None, 则这个方法的行为和dict中一样, 抛出KeyError.如果
default_factory不是None, 则在访问不存在的键时, 调用这个属性为给定键设置默认值。新增实例属性:
default_factory这个属性通过构造函数的第一个参数初始化, 如果不存在, 便设为
None.使用例:
>>> s = 'mississippi' >>> d = defaultdict(int) >>> for k in s: ... d[k] += 1 # dict 中会引发 KeyError ... >>> sorted(d.items()) [('i', 4), ('m', 1), ('p', 2), ('s', 4)]
2.4 namedtuple
namedtuple 是用于创建具有命名字段的元组子类的工厂函数。
使用这个函数有两个步骤:
- 调用函数获取元组子类
- 使用这个元组子类创建具有命名字段的元组
namedtuple 创建的元组子类向后兼容于 tuple.
使用这个函数:
- namedtuple(typename, field_names[, verbose=False][, rename=False])
typename定义返回的元组子类的名称field_names定义字段名, 是一个序列对象。允许的格式:
- 类似于
['x', 'y'] - 用空格或逗号分割字符串: 'x y' 或 'x, y'
- 类似于
rename如果为True,field_names存在非法字段名时, 会自动重命名字段。如:
['abc', 'def', 'ghi', 'abc']–>['abc', '_1', 'ghi', '_3']其中,
abc为重复的字段名。verbose如果为True, 在类的构建之前打印类的定义(感觉没什么用)
例子:
>>> from collections import namedtuple >>> human = namedtuple('human', 'name, age, sex') >>> man = human(name='***', age='**', sex='♂') >>> man human(name='***', age='**', sex='♂') >>> man.sex '♂' >>> man[2] '♂'
2.5 OrderedDict
OrderedDict 和 Dict 不同的是, 它们会记住元素添加的顺序。
OrderedDict 的初始化和 Dict 的初始化是相同的, 但是会记住键的首次插入的顺序。
如果键的值被修改, 它的顺序不会被改变。
2.5.1 方法
- popitem(last=True)
- 如果
last为True, 返回最后的键值对。 如果last为False, 返回最前的键值对 - move_to_end(key, last=True)
(python3) 如果
last为True, 将现有键移动到最后。 荣誉感last为False, 将现有键移动到最前。如果键不存在, 引发KeyError>>> d = OrderedDict.fromkeys('abcde') >>> d.move_to_end('b') >>> ''.join(d.keys()) 'acdeb' >>> d.move_to_end('b', last=False) >>> ''.join(d.keys()) 'bacde'
3 Python3
3.1 ChainMap
ChainMap 可以将多个 dict 或其他映射组合在一起, 这比使用 update 来的快。
ChainMap 初始化:
# ChainMap(*maps) # param: maps 多个映射 >>> m1 = dict(a=1) >>> m2 = dict(b=2) >>> c = ChainMap(m1, m2) >>> c ChainMap({'a': 1}, {'b': 2})
使用例:
>>> c = ChainMap(dict(m=10)) >>> c ChainMap({'m': 10}) >>> d = dict(t=4) >>> c = c.new_child(d) >>> c ChainMap({'t': 4}, {'m': 10}) >>> c['t'] # 访问元素 4 >>> c.maps [{'t': 4}, {'m': 10}] >>> c.parents ChainMap({'m': 10}) >>> c = c.new_child(dict(m=1)) >>> c ChainMap({'m': 1}, {'t': 4}, {'m': 10}) >>> c['m'] 1
3.1.1 方法
- new_child(m=None)
创建一个包含新的
map的新ChainMap. 如果未指定m, 则新的map为一个空的map. 指定m将这个m作为新的map.>>> c = ChainMap(dict(m=10)) >>> c ChainMap({'m': 10}) >>> c = c.new_child() >>> c ChainMap({}, {'m': 10}) >>> c = c.new_child(dict(t=4)) >>> c ChainMap({'t': 4}, {}, {'m': 10})
3.1.2 属性
- maps
可更新的映射列表
>>> c.maps [{'t': 4}, {}, {'m': 10}]- parents
- 等价于
ChainMap(*d.maps[1:]), 返回一个新的ChainMap对象
3.2 Other
除了前面的, 还有三个容器: UserDict, UserList, UserString.
这三个容器分别对 Dict, List, String 进行了封装, 更方便的创建 Dict, List, String 的子类。
如果需要创建自己的 Dict, List, String, 可以考虑从继这三个容器继承。