Fork me on GitHub

py9 基础类型扩展 collections模块

CollectionsOverview

本文将从以下方面讲述collections模块对基础类型的扩展
Alt text

tuple

Alt text
  1. tuple具有一个显著的特性,不可变性,即元组内的内容不可变,但是元组的不可变性也不是绝对的。当元组内部存放可变元素,如列表时,则元组中的列表可变。
  2. 其次元组具有可迭代性是可迭代对象,可以通过for-in进行迭代
  3. 此外元组还具有特别好用的拆包特性

元组的迭代与拆包

迭代
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
posted @ 2018-10-23 08:28  醉生卐梦死  阅读(531)  评论(0编辑  收藏  举报