本文介绍 Python 中 Collections 类中的几种容器,包括
namedtuple
、
deque
、
Counter
、
OrderedDict
和
defaultdict
。
Python 中除了简单的三种容器 (list, dict, tuple) 之外,还有 collections 类中几个非常实用的容器,掌握这几种容器很有可能减少你造轮子的概率咯。
namedtuple
namedtuple
的作用是映射名称到序列元素。这个函数实际上是一个返回 Python 中标准元组类型子类的一个工厂方法。需要传递一个类型名和你需要的字段给它,然后它就会返回一个类,你可以初始化这个类,为你定义的字段传递值等。
>>> from collections import namedtuple
>>> Subscriber = namedtuple("Subscriber", ["addr", "joined"])
>>> sub = Subscriber("[email protected]", "2008-08-08")
>>> sub
Subscriber(addr='[email protected]', joined='2008-08-08')
>>> sub.addr
'[email protected]'
>>> sub.joined
'2008-08-08'
复制代码
同时它和元组类型是可交换的,支持所有普通元祖操作。
>>> len(sub)
>>> a, j = sub
>>> a
'[email protected]'
>>> j
'2008-08-08'
复制代码
另外一个用途就是代替字典,但是不像字典,
namedtuple
是不可以更改的。如果非要修改,可以使用
_replace()
方法。
>>> sub.joined = "2018-03-12"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> sub = sub._replace(joined="2018-03-12")
>>> sub
Subscriber(addr='[email protected]', joined='2018-03-12')
复制代码
deque
deque
提供了一个双端队列,可以从队列两端添加或删除元素。在队列两端插入或删除元素时间复杂度都是
O(1)
,区别于列表,在列表的开头插入或删除元素的时间复杂度为
O(N)
。
>>> from collections import deque
>>> q = deque(maxlen=)
>>> q.append()
>>> q.append()
>>> q.append()
>>> q
deque([, , ], maxlen=)
>>> q.append()
>>> q
deque([, , ], maxlen=)
>>> q.append()
>>> q
deque([, , ], maxlen=)
复制代码
Counter
Counter
是一个计数器,它可以帮助我们针对某项数据进行计数。比如找序列中出现次数最多的元素。也可以进行数学中的加减法。
>>> from collections import Counter
>>> words = [
... 'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
... 'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
... 'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
... 'my', 'eyes', "you're", 'under'
... ]
>>> word_counts = Counter(words)
>>> word_counts.most_common()
[('eyes', ), ('the', ), ('look', )]
>>> morewords = ['why','are','you','not','looking','in','my','eyes']
>>> word_counts.update(morewords)
>>> word_counts['eyes']
>>> a = Counter(words)
>>> b = Counter(morewords)
>>> a
Counter({'eyes': , 'the': , 'look': , 'into': , 'my': , 'around': , 'not': , "don't": , "you're": , 'under': })
>>> b
Counter({'why': , 'are': , 'you': , 'not': , 'looking': , 'in': , 'my': , 'eyes': })
>>> a+b
Counter({'eyes': , 'the': , 'look': , 'my': , 'into': , 'not': , 'around': , "don't": , "you're": , 'under': , 'why': , 'are': , 'you': , 'looking': , 'in': })
>>> a-b
Counter({'eyes': , 'the': , 'look': , 'into': , 'my': , 'around': , "don't": , "you're": , 'under': })
复制代码
OrderedDict
在迭代或序列化这个字典的时候能够控制元素的顺序,在迭代操作的时候它会保持元素被插入时的顺序。
>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d["foo"] =
>>> d["bar"] =
>>> d["spam"] =
>>> d["grok"] =
>>> for key in d:
... print(key, d[key])
...
foo
bar
spam
grok
>>> import json
>>> json.dumps(d)
'{"foo": 1, "bar": 2, "spam": 3, "grok": 4}'
复制代码
OrderdDict
内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元素插入进来的时候,它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会改变键的顺序。因此一个
OrderedDict
的大小是一个普通字典的两倍。
defaultdict
defaultdict
是内置字典类的子类,不需要检查 key 是否存在。
defaultdict
可以很好的实现一对多的字典,如下
d = {
'a' : [1, 2, 3],
'b' : [4, 5]
}
e = {
'a' : {1, 2, 3},
'b' : {4, 5}
}
复制代码
创建方法如下:
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d["a"].append(1)
>>> d["a"].append(2)
>>> d["a"].append(4)
>>> d
defaultdict(<class 'list'>, {'a': [1, 2, 4]})
>>> d = defaultdict(set)
>>> d["a"].add(1)
>>> d["a"].add(2)
>>> d["a"].add(4)
>>> d
defaultdict(<class 'set'>, {'a': {1, 2, 4}})
复制代码
利用
defaultdict
绕过
keyError
异常。
>>> from collections import defaultdict
>>> x = lambda:defaultdict(x)
>>> d = x()
>>> d["a"]["b"] = "q"
>>> d
defaultdict(<function <lambda> at >, {'a': defaultdict(<function <lambda> at >, {'b': 'q'})})
>>> import json
>>> json.dumps(d)
'{"a": {"b": "q"}}'
复制代码
首先要知道
defaultdict
的参数是一个构造函数,比如你可以传入
int
或者
list
。在上面,我传入参数是
x
,也就是说构造函数是
x
,而
x
又是一个参数为
x
的
defaultdict
,所以这样会不断递归,意味着你可以随便传入几层
key
。如果对
lambda
不熟悉的话,可以看看下面的版本。
>>> from collections import defaultdict
>>> def hello():
... return defaultdict(hello)
...
>>> d = hello()
>>> d["a"]["b"] = "q"
>>> d
defaultdict(<function hello at >, {'a': defaultdict(<function hello at >, {'b': 'q'})})
>>> import json
>>> json.dumps(d)
'{"a": {"b": "q"}}'
复制代码
www.ouyangsong.com/posts/62453…
转载于:https://juejin.im/post/5ab51587518825558c475f8d