Jusene's Blog

python3标准库学习之collections

字数统计: 2.4k阅读时长: 12 min
2017/11/02 Share

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
 	@classmethod    
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}})
CATALOG
  1. 1. collections
    1. 1.1. namedtuple()
    2. 1.2. deque()
  2. 2. ChainMap()
  3. 3. Counter()
  4. 4. OrderedDict()
  5. 5. defaultdict()