collections
collections在python的标准库中被称为容器数据类型,collections可以为我们重新定义python的数据基础类型,collections的方法不多,但是却可以在很多地方看见这个模块的使用,是一个常用的python标准库。
namedtuple()
命名元组,创建带命名字段的元组的子类工厂函数,元组我们可以通过索引来定位我们所需要的字段,但是数字还是很不友好的,所以命名元组可以为这个索引命名一个名字。
1 | # collections.namedtuple(typename, field_names, *, verbose=False, rename=False, module=None) 这里有参数槽,一般参数槽后边的默认即可,所以我们关心typename和field_names |
2 | |
3 | from collections import namedtuple |
4 | 'Socket',['IP','PORT']) #防护一个新的被命名为typename的新的元组子类 Socket=namedtuple( |
5 | '127.0.0.1','3306') s=Socket( |
6 | s |
7 | Socket(IP='127.0.0.1', PORT='3306') |
8 | s.IP |
9 | '127.0.0.1' |
10 | s.PORT |
11 | '3306' |
12 | |
13 | '1.1.1.1','1433'] s=[ |
14 | #从这里可知道在子类的初始化中调用的是_make方法 Socket._make(s) |
15 | Socket(IP='1.1.1.1', PORT='1433') |
16 | |
17 | s=Socket._make(s) |
18 | s |
19 | Socket(IP='1.1.1.1', PORT='1433') |
20 | #调用_asdict()可以将放回一个有序字典 s._asdict() |
21 | OrderedDict([('IP', '1.1.1.1'), ('PORT', '1433')]) |
22 | |
23 | s |
24 | Socket(IP='1.1.1.1', PORT='1433') |
25 | '3306') s._replace(PORT= |
26 | Socket(IP='1.1.1.1', PORT='3306') #调用_replace可以替换命名元组的值 |
27 | s |
28 | Socket(IP='1.1.1.1', PORT='1433') |
29 | |
30 | #打印出s的python源码 s._source |
31 | from builtins import property as _property, tuple as _tuple |
32 | from operator import itemgetter as _itemgetter |
33 | from collections import OrderedDict |
34 | class Socket(tuple): |
35 | 'Socket(IP, PORT)' |
36 | __slots__ = () |
37 | _fields = ('IP', 'PORT') |
38 | def __new__(_cls, IP, PORT): |
39 | 'Create new instance of Socket(IP, PORT)' |
40 | return _tuple.__new__(_cls, (IP, PORT)) |
41 |
|
42 | def _make(cls, iterable, new=tuple.__new__, len=len): |
43 | 'Make a new Socket object from a sequence or iterable' |
44 | result = new(cls, iterable) |
45 | if len(result) != 2: |
46 | raise TypeError('Expected 2 arguments, got %d' % len(result)) |
47 | return result |
48 | def _replace(_self, **kwds): |
49 | 'Return a new Socket object replacing specified fields with new values' |
50 | result = _self._make(map(kwds.pop, ('IP', 'PORT'), _self)) |
51 | if kwds: |
52 | raise ValueError('Got unexpected field names: %r' % list(kwds)) |
53 | return result |
54 | def __repr__(self): |
55 | 'Return a nicely formatted representation string' |
56 | return self.__class__.__name__ + '(IP=%r, PORT=%r)' % self |
57 | def _asdict(self): |
58 | 'Return a new OrderedDict which maps field names to their values.' |
59 | return OrderedDict(zip(self._fields, self)) |
60 | def __getnewargs__(self): |
61 | 'Return self as a plain tuple. Used by copy and pickle.' |
62 | return tuple(self) |
63 | IP = _property(_itemgetter(0), doc='Alias for field number 0') |
64 | PORT = _property(_itemgetter(1), doc='Alias for field number 1') |
65 | |
66 | # 返回命名参数 s._fields |
67 | ('IP', 'PORT') |
68 | |
69 | 'IP') # 获得命名参数的值 getattr(s, |
70 | '1.1.1.1' |
71 | |
72 | 'IP':'2.2.2.2','PORT':'1433'} #将字典转换成命名元组 dic={ |
73 | Socket(**dic) |
74 | Socket(IP='2.2.2.2', PORT='1433') |
75 | |
76 | 'Socket',['ip','port','port']) #当我们的命名参数有相同的时候,我们就需要打开参数槽里的重命名模式 Socket=namedtuple( |
77 | Traceback (most recent call last): |
78 | File "<stdin>", line 1, in <module> |
79 | File "/Users/zhangguoxing/.pyenv/versions/3.6.2/lib/python3.6/collections/__init__.py", line 413, in namedtuple |
80 | raise ValueError('Encountered duplicate field name: %r' % name) |
81 | ValueError: Encountered duplicate field name: 'port' |
82 | 'Socket',['ip','port','port'],rename=True) Socket=namedtuple( |
83 | Socket._fields |
84 | ('ip', 'port', '_2') |
85 | '1.1.1.1',port=3306,_2=1433) Socket(ip= |
86 | Socket(ip='1.1.1.1', port=3306, _2=1433) |
deque()
返回一个新的从左到右初始化的的双端队列,deque在双端队列都有相同的O(1)性能,而普通的列表在pop(0)与insert(0,v)上的花费则是O(n),且list不支持双端操作。
1 | # collections.deque([iterable[, maxlen]]) 如果maxlen是None,则这个无限增长,如果限制长度,这个队列在另一端丢弃数据。 |
2 | |
3 | from collections import deque |
4 | d=deque() |
5 | 1) d.append( |
6 | d |
7 | deque([1]) |
8 | 2) #从左端添加 d.appendleft( |
9 | d |
10 | deque([2, 1]) |
11 | d.clear() |
12 | d |
13 | deque([]) |
14 | |
15 | d2=d.copy() |
16 | id(d) |
17 | 4422805712 |
18 | id(d2) |
19 | 4424582544 |
20 | |
21 | 1) d.append( |
22 | 1) d.append( |
23 | 2) d.append( |
24 | 1) d.count( |
25 | 2 |
26 | |
27 | d |
28 | deque([1, 1, 2]) |
29 | 2) d2.append( |
30 | 3) d2.append( |
31 | d.extend(d2) |
32 | d |
33 | deque([1, 1, 2, 2, 3]) |
34 | d.extendleft(d2) |
35 | d |
36 | deque([3, 2, 1, 1, 2, 2, 3]) |
37 | d2 |
38 | deque([2, 3]) |
39 | 2) d.index( |
40 | 1 |
41 | 0,10) d.insert( |
42 | d |
43 | deque([10, 3, 2, 1, 1, 2, 2, 3]) |
44 | d.pop() |
45 | 3 |
46 | d.popleft() |
47 | 10 |
48 | 3) d.remove( |
49 | d |
50 | deque([2, 1, 1, 2, 2]) |
51 | d.reverse() |
52 | d |
53 | deque([2, 2, 1, 1, 2]) |
54 | |
55 | # 这里理解了好久,这里是轮询列表,-1表示一次pop(0) and append(),1表示一次pop() and appendleft() |
56 | 'abcd') d=deque( |
57 | -1) d.rotate( |
58 | d |
59 | deque(['b', 'c', 'd', 'a']) |
60 | 'abcd') d=deque( |
61 | 1) d.rotate( |
62 | d |
63 | deque(['d', 'a', 'b', 'c']) |
64 | 'abcd') d=deque( |
65 | 2) d.rotate( |
66 | d |
67 | deque(['c', 'd', 'a', 'b']) |
68 | 'abcd') d=deque( |
69 | -2) d.rotate( |
70 | d |
71 | deque(['c', 'd', 'a', 'b']) |
72 | |
73 | # 限制队列的长度 |
74 | 'abcd',2) d=deque( |
75 | d |
76 | deque(['c', 'd'], maxlen=2) |
77 | 'a') d.append( |
78 | d |
79 | deque(['d', 'a'], maxlen=2) |
80 | 'a') d.appendleft( |
81 | d |
82 | deque(['a', 'd'], maxlen=2) |
83 | |
84 | |
85 | # 简单实例应用 |
86 | #实现tail功能 |
87 | with open('access.log') as f: |
88 | data=collections.deque(f,10) |
89 | for i in data: |
90 | print(i) |
ChainMap()
类似于dict的类,用于创建多个映射的单一视图
1 | # collections.ChainMap(*maps) 类似itertools中的chain,而这里的主要是为了字典 |
2 | |
3 | 'k':'v','k1':'v1'} d={ |
4 | 'k':'v1','k2':'v2'} d2={ |
5 | collections.ChainMap(d,d2) |
6 | ChainMap({'k': 'v', 'k1': 'v1'}, {'k': 'v1', 'k2': 'v2'}) |
7 | 'k'] # 可见在这个视图中只会匹配最新匹配到的键值对 collections.ChainMap(d,d2)[ |
8 | 'v' |
9 | dic=collections.ChainMap(d,d2) |
10 | # maps |
11 | # 返回映射列表 dic.maps |
12 | [{'k': 'v', 'k1': 'v1'}, {'k': 'v1', 'k2': 'v2'}] |
13 | 'k3':'v3'} d3={ |
14 | # new_child(m=None) |
15 | # 添加新的视图映射 dic.new_child(d3) |
16 | ChainMap({'k3': 'v3'}, {'k': 'v', 'k1': 'v1'}, {'k': 'v1', 'k2': 'v2'}) |
17 | # parents |
18 | # 属性返回一个新的ChainMap,其中包含当前实例中除第一个之外的所有映射。 dic.parents |
19 | ChainMap({'k': 'v1', 'k2': 'v2'}) |
Counter()
命令子类计数可使用的对象
1 | # collections.Counter([iterable-or-mapping]) 元素的计数器,返回的是无序列表 |
2 | |
3 | c=collections.Counter() |
4 | c |
5 | Counter() |
6 | 'abcda') c=collections.Counter( |
7 | c |
8 | Counter({'a': 2, 'b': 1, 'c': 1, 'd': 1}) |
9 | 'a':2,'b':3}) c=collections.Counter({ |
10 | c |
11 | Counter({'b': 3, 'a': 2}) |
12 | 2,dogs=4) c=collections.Counter(cats= |
13 | c |
14 | Counter({'dogs': 4, 'cats': 2}) |
15 | 'pigs'] c[ |
16 | 0 |
17 | 'pigs']=5 c[ |
18 | c |
19 | Counter({'pigs': 5, 'dogs': 4, 'cats': 2}) |
20 | # elements() |
21 | # 将计数的值重新转化为迭代对象 sorted(c.elements()) |
22 | ['cats', 'cats', 'dogs', 'dogs', 'dogs', 'dogs', 'pigs', 'pigs', 'pigs', 'pigs', 'pigs'] |
23 | # most_common(n) |
24 | '1342134241313413143').most_common(3) # 快速统计出最多的n的要素 collections.Counter( |
25 | [('1', 6), ('3', 6), ('4', 5)] |
26 | |
27 | '233') #元素从一个iterable减去另一个iterable的映射中减去 d=collections.Counter( |
28 | '122') c=collections.Counter( |
29 | c |
30 | Counter({'2': 2, '1': 1}) |
31 | d |
32 | Counter({'3': 2, '2': 1}) |
33 | # subtract(iterable-or-mapping) |
34 | c.subtract(d) |
35 | c |
36 | Counter({'1': 1, '2': 1, '3': -2}) |
37 | # fromkeys(iterable) 这个方法不是对于Counter对象 |
38 | '123',2)) Counter({}.fromkeys( |
39 | Counter({'1': 2, '2': 2, '3': 2}) |
40 | # update(iterable-or-mapping) |
41 | '2') #添加映射内容 c.update( |
42 | c |
43 | Counter({'2': 3, '1': 2, '3': 2}) |
44 | '3':5}) c.update({ |
45 | c |
46 | Counter({'3': 7, '2': 3, '1': 2}) |
OrderedDict()
有序字典,字典默认无序,这个子类封装可以将字典按添加的顺序有序排列。
1 | # collections.OrderedDict([items]) |
2 | |
3 | d=collections.OrderedDict() |
4 | d |
5 | OrderedDict() |
6 | 'a']=1 d[ |
7 | 'b']=2 d[ |
8 | d |
9 | OrderedDict([('a', 1), ('b', 2)]) |
10 | # popitem(last=True) |
11 | d.popitem() |
12 | ('b', 2) |
13 | |
14 | # move_to_end(key,last=True) |
15 | d |
16 | OrderedDict([('a', 1), ('c', 3)]) |
17 | 'a') d.move_to_end( |
18 | d |
19 | OrderedDict([('c', 3), ('a', 1)]) |
20 | 'c',last=False) d.move_to_end( |
21 | d |
22 | OrderedDict([('c', 3), ('a', 1)]) |
defaultdict()
返回一个新的dictionary类对象。defaultdict是内置的命令类的子类。它覆盖了一种方法,并添加了一个可写的实例变量。
1 | # collections.defaultdict([default_factory[, ...]] 字典的默认工厂数据类型 |
2 | |
3 | l=collections.defaultdict(list) |
4 | l |
5 | defaultdict(<class 'list'>, {}) |
6 | 'test'] l[ |
7 | [] |
8 | l |
9 | defaultdict(<class 'list'>, {'test': []}) |
10 | 'test']=1 l[ |
11 | l |
12 | defaultdict(<class 'list'>, {'test': 1}) |
13 | |
14 | # 快速创建出一键多值 |
15 | l=collections.defaultdict(list) |
16 | l |
17 | defaultdict(<class 'list'>, {}) |
18 | 'test'].append(1) l[ |
19 | 'test'].append(2) l[ |
20 | l |
21 | defaultdict(<class 'list'>, {'test': [1, 2]}) |
22 | |
23 | l=collections.defaultdict(set) |
24 | 'test'].add(1) l[ |
25 | 'test'].add(2) l[ |
26 | 'test'].add(3) l[ |
27 | l |
28 | defaultdict(<class 'set'>, {'test': {1, 2, 3}}) |
29 | 'test'].add(1) l[ |
30 | l |
31 | defaultdict(<class 'set'>, {'test': {1, 2, 3}}) |