py9 基础类型扩展 collections模块
CollectionsOverview
本文将从以下方面讲述collections模块对基础类型的扩展
tuple
- tuple具有一个显著的特性,不可变性,即元组内的内容不可变,但是元组的不可变性也不是绝对的。当元组内部存放可变元素,如列表时,则元组中的列表可变。
- 其次元组具有可迭代性是可迭代对象,可以通过for-in进行迭代
- 此外元组还具有特别好用的拆包特性
元组的迭代与拆包
迭代
tuple_1 = ('weilianixn', 12345, 'cs', 18, 'male') for i in tuple_1: print(i)
拆包
tuple_1 = ('weilianixn', 12345, 'cs', 18, 'male') name, password, major,*part = tuple_1 print(name) print(password) print(part) # [18, 'male']
拆包时注意不要在for循环中进行拆包
for name, password, job, age, part in tuple_1: ValueError: too many values to unpack (expected 5)
namedtuple
namedtuple是一个函数,返回一个继承了tuple的简易类,用属性而不是索引来引用tuple的元素。用namedtuple生成的类很省空间,省去了class定义类的很多内置函数。并且用该类生成的对象还可拆包。主要研究_make和_asdict方法
# class User: # def __init__(self, name, password): # self.name = name # self.password = password # # user = User('wei', 1233214) # print(user.password, user.name) # 与下面等价 from collections import namedtuple User_tuple = namedtuple('User_t', ['name', 'password', 'major', 'age']) user_t = User_tuple(name='wei', password=2131, major='cs', age=18) # tuple_1 = ('weilianixn', 12345, 'cs') # user_t = User_tuple(*tuple_1, 18) # *不加tuple_1会判定成一个变量 # dict_1 = { # 'name': 'wei', # 'password': '123213', # 'major': 'cs' # } # user_t = User_tuple(**dict_1, age=18) print(user_t.name, user_t.password, user_t.major) print(type(user_t))
-
_make方法make里面传递一个可迭代对象,数量要与namedtuple生成的相符
from collections import namedtuple User_tuple = namedtuple('User_t', ['name', 'password', 'major', 'age']) # list_1 = ['weilianixn', 12345, 'cs', 18] # dict_1 = { # 'name': 'wei', # 'password': '123213', # 'major': 'cs', # 'age': 18 # } tuple_1 = ('weilianixn', 12345, 'cs', 18) user_t = User_tuple._make(tuple_1)
_make()方法和*的作用类似,相当于解析了括号内的可迭代对象,传的是括号内的值
-
_ asdict方法将我们的tuple转换成字典
User_tuple = namedtuple('User_t', ['name', 'password', 'major','age']) list_1 = ['weilianixn', 12345, 'cs',18] user_t = User_tuple._make(list_1) dict_12 = user_t._asdict() print(dict_12) # OrderedDict([('name', 'weilianixn'), ('password', 12345), ('major', 'cs'), ('age', 18)])
defaultdict
在说明defaultdict之前我们先说一下普通dict使用时的缺陷,比如在做用户数量统计时
user = ['wei1', 'wei2', 'wei1', 'wei3', 'wei2', 'wei3', 'wei1'] user_dict = {} for i in user: if i in user_dict: user_dict[i] += 1 else: user_dict[i] = 1 print(user_dict) # {'wei1': 3, 'wei2': 2, 'wei3': 2}
上面方法可以进行优化,把for循环优化如下,结果相同
for i in user: user_dict.setdefault(i, 0) user_dict[i] += 1
使用defaultdict来创建的话如下,defaultdict只接收可调用对象和none
from collections import defaultdict user = ['wei1', 'wei2', 'wei1', 'wei3', 'wei2', 'wei3', 'wei1'] user_dict = defaultdict(int) for i in user: user_dict[i] += 1
defaultdict传list或int等就是直接把值初始化成空列表或者0等,若想传有结构的字典或其他自定义的结构采用以下方法
from collections import defaultdict def group_d(): return { 'name': '', 'nums': 0 } group_dict = { 'group': { 'name': '', 'nums': 0 } } user_dict = defaultdict(group_d) # 不能传group_dict,不可是可调用对象 user_dict['group']
deque
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
>>> from collections import deque >>> q = deque(['a', 'b', 'c']) >>> q.append('x') >>> q.appendleft('y') >>> q deque(['y', 'a', 'b', 'c', 'x'])
deque需要传递一个可迭代对象,传递字典时以字典的key生成一个列表
from collections import deque deq = deque([1,2,3,4]) deq1 = deque({'name':'wei', 'age':18}) print(deq1) # deque(['name', 'age'])
deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。
deque可以限定队列的长度,先入先出,可以实现保留最后N个元素
下面是实现删除文件的最后一行
from collections import deque deq = deque(maxlen=5) print(deq.__len__()) with open('02第二模块之三体语录', 'r+', encoding='utf-8') as f: with open('new', 'w', encoding='utf-8') as f1: while True: line = f.readline() if line: deq.append(line) if deq.__len__() == 5: f1.write(deq[0]) else: break for i in range(3): f1.write(deq[i + 1])
Counter
Counter是一个简单的计数器,例如,统计字符出现的个数,是dict的一个子类,返回值是一个collections.Counter,类似于defaultdict,元素被储存为字典的keys,他们的计数被储存为字典的values
from collections import Counter li = ['wei1', 'wei2', 'wei1', 'wei3', 'wei2', 'wei3', 'wei1'] counter = Counter(li) # Counter({'name': 'wei', 'age': 18}) c = Counter() for ch in 'programming': c[ch] = c[ch] + 1 # 只有defaultdict才能这样用 print(c) # Counter({'r': 2, 'g': 2, 'm': 2, 'p': 1, 'o': 1, 'a': 1, 'i': 1, 'n': 1})
-
Count.update()可以在原统计的基础上更进一步统计,可接受可迭代对象,也可接受另一个count对象,该方法是在原函数上进行修改,返回值为none
-
Count.most_common()接收数字参数,统计出现前几多的元素
-
elements()类似于字典中的keys()方法
-
values()类似于字典中的vaues()方法
-
update()类似于字典中的update()方法对计数器进行更新
-
substract()对计数器进行反向计数
from collections import Counter c = Counter('which') c.subtract('witch') # Counter({'c': 0, 'h': 1, 'i': 0, 't': -1, 'w': 0}) c.subtract('witch') # Counter({'c': -1, 'h': 0, 'i': -1, 't': -2, 'w': -1})
OrderedDict
可以实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最早添加的Key。
-
move_to_end()可以吧一个键值对调到最后
-
popitem()默认把排在最后的一个键值对删除
-
pop(key)根据传入的key把相应的键值对删除并返回value
ChainMap
ChainMap能够将多个dict联合起来进行操作
from collections import ChainMap dict1 = {'a': "w1", 'b': 'w2', 'c': 'w3'} dict2 = {'c': 'w2', 'd': 'w4', 'e': 'w5'} new_dict = ChainMap(dict1, dict2) dict1['a'] = 'w' print(new_dict) for item in new_dict.items(): print(item) print(new_dict.maps)
结果为
ChainMap({‘a’: ‘w’, ‘b’: ‘w2’, ‘c’: ‘w3’}, {‘c’: ‘w2’, ‘d’: ‘w4’, ‘e’: ‘w5’})(‘c’, ‘w3’)(‘d’, ‘w4’)(‘e’, ‘w5’)(‘a’, ‘w’)(‘b’, ‘w2’)[{‘a’: ‘w’, ‘b’: ‘w2’, ‘c’: ‘w3’}, {‘c’: ‘w2’, ‘d’: ‘w4’, ‘e’: ‘w5’}]
-
new_child()相当于update,对原数据进行更新。
-
parents()根据原ChainMap进行[1:]切片,返回一个新的ChainMap