天天看点

Python 中的容器

本文介绍 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