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=namedtuple('Socket',['IP','PORT']) #防护一个新的被命名为typename的新的元组子类 |
5 | s=Socket('127.0.0.1','3306') |
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 | s=['1.1.1.1','1433'] |
14 | Socket._make(s) #从这里可知道在子类的初始化中调用的是_make方法 |
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 | s._asdict() #调用_asdict()可以将放回一个有序字典 |
21 | OrderedDict([('IP', '1.1.1.1'), ('PORT', '1433')]) |
22 | |
23 | s |
24 | Socket(IP='1.1.1.1', PORT='1433') |
25 | s._replace(PORT='3306') |
26 | Socket(IP='1.1.1.1', PORT='3306') #调用_replace可以替换命名元组的值 |
27 | s |
28 | Socket(IP='1.1.1.1', PORT='1433') |
29 | |
30 | s._source #打印出s的python源码 |
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 | getattr(s,'IP') # 获得命名参数的值 |
70 | '1.1.1.1' |
71 | |
72 | dic={'IP':'2.2.2.2','PORT':'1433'} #将字典转换成命名元组 |
73 | Socket(**dic) |
74 | Socket(IP='2.2.2.2', PORT='1433') |
75 | |
76 | Socket=namedtuple('Socket',['ip','port','port']) #当我们的命名参数有相同的时候,我们就需要打开参数槽里的重命名模式 |
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=namedtuple('Socket',['ip','port','port'],rename=True) |
83 | Socket._fields |
84 | ('ip', 'port', '_2') |
85 | Socket(ip='1.1.1.1',port=3306,_2=1433) |
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 | d.append(1) |
6 | d |
7 | deque([1]) |
8 | d.appendleft(2) #从左端添加 |
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 | d.append(1) |
22 | d.append(1) |
23 | d.append(2) |
24 | d.count(1) |
25 | 2 |
26 | |
27 | d |
28 | deque([1, 1, 2]) |
29 | d2.append(2) |
30 | d2.append(3) |
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 | d.index(2) |
40 | 1 |
41 | d.insert(0,10) |
42 | d |
43 | deque([10, 3, 2, 1, 1, 2, 2, 3]) |
44 | d.pop() |
45 | 3 |
46 | d.popleft() |
47 | 10 |
48 | d.remove(3) |
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 | d=deque('abcd') |
57 | d.rotate(-1) |
58 | d |
59 | deque(['b', 'c', 'd', 'a']) |
60 | d=deque('abcd') |
61 | d.rotate(1) |
62 | d |
63 | deque(['d', 'a', 'b', 'c']) |
64 | d=deque('abcd') |
65 | d.rotate(2) |
66 | d |
67 | deque(['c', 'd', 'a', 'b']) |
68 | d=deque('abcd') |
69 | d.rotate(-2) |
70 | d |
71 | deque(['c', 'd', 'a', 'b']) |
72 | |
73 | # 限制队列的长度 |
74 | d=deque('abcd',2) |
75 | d |
76 | deque(['c', 'd'], maxlen=2) |
77 | d.append('a') |
78 | d |
79 | deque(['d', 'a'], maxlen=2) |
80 | d.appendleft('a') |
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 | d={'k':'v','k1':'v1'} |
4 | d2={'k':'v1','k2':'v2'} |
5 | collections.ChainMap(d,d2) |
6 | ChainMap({'k': 'v', 'k1': 'v1'}, {'k': 'v1', 'k2': 'v2'}) |
7 | collections.ChainMap(d,d2)['k'] # 可见在这个视图中只会匹配最新匹配到的键值对 |
8 | 'v' |
9 | dic=collections.ChainMap(d,d2) |
10 | # maps |
11 | dic.maps # 返回映射列表 |
12 | [{'k': 'v', 'k1': 'v1'}, {'k': 'v1', 'k2': 'v2'}] |
13 | d3={'k3':'v3'} |
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 | dic.parents # 属性返回一个新的ChainMap,其中包含当前实例中除第一个之外的所有映射。 |
19 | ChainMap({'k': 'v1', 'k2': 'v2'}) |
Counter()
命令子类计数可使用的对象
1 | # collections.Counter([iterable-or-mapping]) 元素的计数器,返回的是无序列表 |
2 | |
3 | c=collections.Counter() |
4 | c |
5 | Counter() |
6 | c=collections.Counter('abcda') |
7 | c |
8 | Counter({'a': 2, 'b': 1, 'c': 1, 'd': 1}) |
9 | c=collections.Counter({'a':2,'b':3}) |
10 | c |
11 | Counter({'b': 3, 'a': 2}) |
12 | c=collections.Counter(cats=2,dogs=4) |
13 | c |
14 | Counter({'dogs': 4, 'cats': 2}) |
15 | c['pigs'] |
16 | 0 |
17 | c['pigs']=5 |
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 | collections.Counter('1342134241313413143').most_common(3) # 快速统计出最多的n的要素 |
25 | [('1', 6), ('3', 6), ('4', 5)] |
26 | |
27 | d=collections.Counter('233') #元素从一个iterable减去另一个iterable的映射中减去 |
28 | c=collections.Counter('122') |
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 | Counter({}.fromkeys('123',2)) |
39 | Counter({'1': 2, '2': 2, '3': 2}) |
40 | # update(iterable-or-mapping) |
41 | c.update('2') #添加映射内容 |
42 | c |
43 | Counter({'2': 3, '1': 2, '3': 2}) |
44 | c.update({'3':5}) |
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 | d['a']=1 |
7 | d['b']=2 |
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 | d.move_to_end('a') |
18 | d |
19 | OrderedDict([('c', 3), ('a', 1)]) |
20 | d.move_to_end('c',last=False) |
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 | l['test'] |
7 | [] |
8 | l |
9 | defaultdict(<class 'list'>, {'test': []}) |
10 | l['test']=1 |
11 | l |
12 | defaultdict(<class 'list'>, {'test': 1}) |
13 | |
14 | # 快速创建出一键多值 |
15 | l=collections.defaultdict(list) |
16 | l |
17 | defaultdict(<class 'list'>, {}) |
18 | l['test'].append(1) |
19 | l['test'].append(2) |
20 | l |
21 | defaultdict(<class 'list'>, {'test': [1, 2]}) |
22 | |
23 | l=collections.defaultdict(set) |
24 | l['test'].add(1) |
25 | l['test'].add(2) |
26 | l['test'].add(3) |
27 | l |
28 | defaultdict(<class 'set'>, {'test': {1, 2, 3}}) |
29 | l['test'].add(1) |
30 | l |
31 | defaultdict(<class 'set'>, {'test': {1, 2, 3}}) |