collections模块
这个模块实现了特定目标的容器,以提供Python标准内建容器 dict、list、set、tuple 的替代选择, 使用更高效
类 | 说明 |
---|---|
Counter | 字典的子类,提供了可哈希对象的计数功能 |
defaultdict | 字典的子类,提供了一个工厂函数,为字典查询提供了默认值 |
OrderedDict | 字典的子类,保留了他们被添加的顺序 |
namedtuple | 创建命名元组子类的工厂函数 |
deque | 双端队列,实现了在两端快速添加(append)和弹出(pop) |
ChainMap | 类似字典的容器类,将多个映射集合到一个视图里面 |
Counter类
测试demo
'''快速计数,默认增加的k的value是0
Counter对象有一个字典接口,如果引用的键没有任何记录,就返回一个0,而不是弹出一个 KeyError'''
cnt = Counter()
for word in ['red','blue','red','green']:cnt[word]+=1
cnt['a']+=1
print(cnt)
>> Counter({'red': 2, 'blue': 1, 'green': 1, 'a': 1})
'''elements()返回一个迭代器,每个元素重复计数的个数。元素顺序是任意的。如果一个元素的计数小于1, elements() 就会忽略它。'''
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']
c = Counter() # a new, empty counter
c1 = Counter('gallahad') # a new counter from an iterable
c2 = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping
c3 = Counter(cats=4, dogs=8) # a new counter from keyword args
words = re.findall(r'\w+', open('hamlet.txt').read().lower())
print(dict(Counter(words).most_common(5))) # 排行前五
#{'asd': 92, 'asqqw': 46, 'qwdqwdqwd': 46, 'qwdqwdqdqdqd': 46, 'qwdqda': 46}
ChainMap类
合并映射字典,比update效率要高
import os, argparse
defaults = {'color': 'red', 'user': 'guest'}
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = {k: v for k, v in vars(namespace).items() if v is not None}
combined = ChainMap(command_line_args, os.environ, defaults)
print(combined)
print(combined['color'])
print(combined['user'])
print(combined['PWD'])
#实现内部可更新
class DeepChainMap(ChainMap):
'Variant of ChainMap that allows direct updates to inner scopes'
def __setitem__(self, key, value):
for mapping in self.maps:
if key in mapping:
mapping[key] = value
return
self.maps[0][key] = value
def __delitem__(self, key):
for mapping in self.maps:
if key in mapping:
del mapping[key]
return
raise KeyError(key)
d = DeepChainMap({'zebra': 'black'}, {'elephant': 'blue'}, {'lion': 'yellow'})
d['lion'] = 'orange'
d['snake'] = 'red'
print(d)
DefaultDict
defaultdict的一个典型用法是使用其中一种内置类型(如str、int、list或dict)作为默认工厂,因为这些内置类型在没有参数调用时返回空类型。
- 使用str作为default_factory的例子
>>> d = collections.defaultdict(str)
>>> d
defaultdict(<class 'str'>, {})
>>> d['hello']
''
>>> d
defaultdict(<class 'str'>, {'hello': ''})
# 普通字典调用不存在的键时,将会抛异常
>>> e = {}
>>> e['hello']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'hello'
- 使用int作为default_factory的例子
>>> from collections import defaultdict
>>> fruit = defaultdict(int)
>>> fruit['apple'] += 2
>>> fruit
defaultdict(<class 'int'>, {'apple': 2})
>>> fruit
defaultdict(<class 'int'>, {'apple': 2})
>>> fruit['banana'] # 没有对象时,返回0
0
>>> fruit
defaultdict(<class 'int'>, {'apple': 2, 'banana': 0})
- 使用list作为default_factory的例子:
>>> s = [('NC', 'Raleigh'), ('VA', 'Richmond'), ('WA', 'Seattle'), ('NC', 'Asheville')]
>>> d = collections.defaultdict(list)
>>> for k,v in s:
... d[k].append(v)
...
>>> d
defaultdict(<class 'list'>, {'NC': ['Raleigh', 'Asheville'], 'VA': ['Richmond'], 'WA': ['Seattle']})
OrderedDict
collections.OrderedDict类提供了保留他们添加顺序的字典对象。
Python字典中的键的顺序是任意的:它们不受添加的顺序的控制。
namedtuple
三种定义命名元组的方法:第一个参数是命名元组的构造器(如下的:Person,Human)
>>> from collections import namedtuple
>>> Person = namedtuple('Person', ['age', 'height', 'name'])
>>> Human = namedtuple('Human', 'age, height, name')
>>> Human2 = namedtuple('Human2', 'age height name')
实例化命令元组
>>> tom = Person(30,178,'Tom')
>>> jack = Human(20,179,'Jack')
>>> tom
Person(age=30, height=178, name='Tom')
>>> jack
Human(age=20, height=179, name='Jack')
>>> tom.age #直接通过 实例名+.+属性 来调用
30
>>> jack.name
'Jack'
deque双端队列
点击使用查看博主总结:https://blog.csdn.net/qq_17480053/article/details/51482659
列表 VS 双端队列
append(x):把元素x添加到队列的右端
appendleft(x):把元素x添加到队列的左端
clear():清空队列中所有元素
copy():创建队列的浅拷贝
count(x):计算队列中等于x元素的个数
extend(iterable):在队列右端通过添加元素扩展
extendleft(iterable):在队列左端通过添加元素扩展
index(x[, start[, stop]]):返回x元素在队列中的索引,放回第一个匹配,如果没有找到抛ValueError
insert(i, x):在队列的i索引处,插入x元素
pop():移除并返回deque右端的元素,如果没有元素抛IndexError
popleft():移除并返回deque左端的元素,如果没有元素抛IndexError
remove(value):删除第一个匹配value的元素,如果没有找到抛ValueError
reverse():在原地反转队列中的元素
rotate(n):把队列左端n个元素放到右端,如果为负值,右端到左端。如果n为1,等同d.appendleft(d.pop())
maxlen:只读属性,队列中的最大元素数
总结:
- 双端队列支持线程安全,在双端队列的任何一端执行添加和删除操作,它们的内存效率几乎相同(时间复杂度为O(1))。
- 虽然list也支持类似的操作,但是它对定长列表的操作表现很不错,而当遇到pop(0)和insert(0, v)这样既改变了列表的长度又改变其元素位置的操作时,其时间复杂度就变为O(n)了。
- 在双端队列中最好不使用切片和索引,你可以用popleft和appendleft方法,双端队列对这些操作做了优化。在两端的索引访问时间复杂度为O(1),但是访问中间元素的时间复杂度为O(n),速度较慢,对于快速随机的访问,还是用列表代替。
列表用于随机访问和定长数据的操作,包括切片,而双端队列适用于在两端压入或弹出元素,索引(但不包括切片)的效率可能低于列表。