collections模块
在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。
1.namedtuple: 生成可以使用名字来访问元素内容的tuple
2.deque: 双端队列,可以快速的从另外一侧追加和推出对象
3.Counter: 计数器,主要用来计数
4.OrderedDict: 有序字典
5.defaultdict: 带有默认值的字典
namedtuple
我们知道tuple
可以表示不变集合,例如,一个点的二维坐标就可以表示成:
>>> p = (1, 2)
但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。
这时,namedtuple
就派上了用场:
>>> from collections import namedtuple >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(1, 2) >>> p.x >>> p.y
类似的,如果要用坐标和半径表示一个圆,也可以用namedtuple
定义:
#namedtuple('名称', [属性list]): Circle = namedtuple('Circle', ['x', 'y', 'r'])
deque
使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> from collections import deque 2 >>> q = deque(['a', 'b', 'c']) 3 >>> q.append('x') 4 >>> q.appendleft('y') 5 >>> q 6 deque(['y', 'a', 'b', 'c', 'x'])
deque除了实现list的append()
和pop()
外,还支持appendleft()
和popleft()
,这样就可以非常高效地往头部添加或删除元素。
OrderedDict
使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
如果要保持Key的顺序,可以用OrderedDict
:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> from collections import OrderedDict 2 >>> d = dict([('a', 1), ('b', 2), ('c', 3)]) 3 >>> d # dict的Key是无序的 4 {'a': 1, 'c': 3, 'b': 2} 5 >>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) 6 >>> od # OrderedDict的Key是有序的 7 OrderedDict([('a', 1), ('b', 2), ('c', 3)])
注意,OrderedDict
的Key会按照插入的顺序排列,不是Key本身排序:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> od = OrderedDict() 2 >>> od['z'] = 1 3 >>> od['y'] = 2 4 >>> od['x'] = 3 5 >>> od.keys() # 按照插入的Key的顺序返回 6 ['z', 'y', 'x']
defaultdict
有如下值集合 [
11
,
22
,
33
,
44
,
55
,
66
,
77
,
88
,
99
,
90.
..],将所有大于
66
的值保存至字典的第一个key中,将小于
66
的值保存至第二个key的值中。
即: {
'k1'
: 大于
66
,
'k2'
: 小于
66
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 li = [11,22,33,44,55,77,88,99,90] 2 result = {} 3 for row in li: 4 if row > 66: 5 if 'key1' not in result: 6 result['key1'] = [] 7 result['key1'].append(row) 8 else: 9 if 'key2' not in result: 10 result['key2'] = [] 11 result['key2'].append(row) 12 print(result) 13 14 原生字典的解决方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from collections import defaultdict 2 3 values = [11, 22, 33,44,55,66,77,88,99,90] 4 5 my_dict = defaultdict(list) 6 7 for value in values: 8 if value>66: 9 my_dict['k1'].append(value) 10 else: 11 my_dict['k2'].append(value) 12 13 defaultdict字典解决方法
使用dict
时,如果引用的Key不存在,就会抛出KeyError
。如果希望key不存在时,返回一个默认值,就可以用defaultdict
:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> from collections import defaultdict 2 >>> dd = defaultdict(lambda: 'N/A') 3 >>> dd['key1'] = 'abc' 4 >>> dd['key1'] # key1存在 5 'abc' 6 >>> dd['key2'] # key2不存在,返回默认值 7 'N/A' 8 9 例2
Counter
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。
c = Counter('abcdeabcdabcaba') print c 输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
random模块
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 >>> import random 2 #随机小数 3 >>> random.random() # 大于0且小于1之间的小数 4 0.7664338663654585 5 >>> random.uniform(1,3) #大于1小于3的小数 6 1.6270147180533838 7 #恒富:发红包 8 9 #随机整数 10 >>> random.randint(1,5) # 大于等于1且小于等于5之间的整数 11 >>> random.randrange(1,10,2) # 大于等于1且小于10之间的奇数 12 13 14 #随机选择一个返回 15 >>> random.choice([1,'23',[4,5]]) # #1或者23或者[4,5] 16 #随机选择多个返回,返回的个数为函数的第二个参数 17 >>> random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合 18 [[4, 5], '23'] 19 20 21 #打乱列表顺序 22 >>> item=[1,3,5,7,9] 23 >>> random.shuffle(item) # 打乱次序 24 >>> item 25 [5, 1, 3, 7, 9] 26 >>> random.shuffle(item) 27 >>> item 28 [5, 9, 7, 1, 3]
练习:生成随机验证码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import random 2 3 def v_code(): 4 5 code = '' 6 for i in range(5): 7 8 num=random.randint(0,9) 9 alf=chr(random.randint(65,90)) 10 add=random.choice([num,alf]) 11 code="".join([code,str(add)]) 12 13 return code 14 15 print(v_code()) 16 17 生成随机验证码 18 # 1题:4位,全数字的随机验证码 19 import random 20 print(random.sample([i for i in range(0,10)],4)) 21 # 2题:4位,数字与字母(不区分)相结合的随机验证码. 22 val = [chr(i) for i in range(65,123) if i<91 or i>96 ] 23 for i in range(0,10): 24 val.append(i) 25 print(random.sample(val,4))