1、collections模块介绍
2、tuple
3、namedtuple :常用
4、defaultdict :常用
5、deque
6、Counter
7、OrderedDict
8、ChainMap
9、总结
1、collections模块
import collections
# __all__ 可使用模块
# 抽象基类 interface
from collections.abc import *
2、tuple
不可变类型:数字、字符串、元组均是不可变类型
可迭代iterable(即可遍历)
元组拆包
tuple不可变不是绝对的
tuple
VS list
- immutable的重要性:性能优化、线路安全、可以作为dict的key、拆包特性
- tuple类似C语言中struct,list类似array
t = ("123","456")
# t[0]="123" # TypeError: 'tuple' object does not support item assignment
user_tuple = ("bai",29,170)
name,age,height = user_tuple # 拆包
name,*other = user_tuple # 也可如此拆包
print(name,other) # bai [29, 170]
t = ("bai",[1,2])
t[1].append(3) # tuple不可变,不是绝对的;但是不建议将可变对象放入tuple中
# 可hash对象可以作为dict的key
# 不可变对象是hashable对象
dic = {(1,):1}
dic2 = {[1]:1} # TypeError: unhashable type: 'list'
3、namedtuple
定义命名元组,让元组的每个元素可以通过类似对象属性的方法用“.属性”及其方便的取值
class User:
def __init__(self,name,age):
self.name = name
self.age = age
user = User(name="bai",age=29)
print(user.name,user.age) # 使用.调用属性或方法
# namedtuple
from collections import namedtuple
# 类似上述Class;节省空间,提升效率;代码简单
User = namedtuple("User",["name","age"])
user = User(name="bai",age=29)
print(user.name,user.age)
# def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):
"""Returns a new subclass of tuple with named fields.
>>> Point = namedtuple('Point', ['x', 'y'])
>>> Point.__doc__ # docstring for the new class
'Point(x, y)'
>>> p = Point(11, y=22) # instantiate with positional args or keywords
>>> p[0] + p[1] # indexable like a plain tuple
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> d = p._asdict() # convert to a dictionary
>>> d['x']
11
>>> Point(**d) # convert from a dictionary
Point(x=11, y=22)
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
Point(x=100, y=22)
"""
# 初始化
user_tuple = ("bai",29)
user2 = User(*user_tuple) # # 必须与你定义的时候的一一对应,不可多不可少
User = namedtuple("User",["name","age","height"])
user3 = User(*user_tuple,"第三参数")
# 引申:函数参数
def ask(*args,**kwargs): # 任意方式传参
pass
ask("bai",29)
ask(name="bai",age=29,height=170)
# _make方法 _make(cls, iterable: Iterable[Any]) -> NamedTuple
user_tuple=("t","u","p")
user_list = [1,2,3]
user_dict ={"n":"d","a":"i","h":"c"}
user4 = User._make(user_tuple) # 用于创建实例,可以不限传参类型,仅iterable即可
user5 = User._make(user_list)
user6 = User._make(user_dict)
# _asdict()方法
# user7 = User._asdict()
# TypeError: _asdict() missing 1 required positional argument: 'self'
user_info_dict = user3._asdict()
print(user_info_dict) # {'name': 'bai', 'age': 29, 'height': '第三参数'}
# 支持拆包
n,a,h=user3
print(n,a,h)
4、defaultdict
user_dict = {}
users = ["b","a","i","b","c"]
# 计数
for i in users:
if i in user_dict:
user_dict[i]+=1
else:
# 首次出现,数量计为1
user_dict[i]=1
print(user_dict)
# 第2版 setdefault
user_dict2 = dict()
for i in users:
user_dict2.setdefault(i,0) # 若字典中key不存在,则插入key时设置默认值
user_dict2[i] +=1 # 若上行代码是1,则再次+1会有问题
print(user_dict2)
# def setdefault(self, *args, **kwargs): # real signature unknown
# Insert key with a value of default if key is not in the dictionary.
# Return the value for key if key is in the dictionary, else default.
from collections import defaultdict
# defaultdict 具有dict的属性
# default_dict = defaultdict(users)
# TypeError: first argument must be callable or None
default_dict = defaultdict(list) # 传参为可调用对象,如funtion ;defaultdict(<class 'list'>, {})
default_dict["bai"]
# 为字典的key默认value
image.png
# 第3版:defaultdict
user_dict3 = defaultdict(int) # 不存在的key默认设置0
for i in users:
user_dict3[i] +=1
print(user_dict3) # defaultdict(<class 'int'>, {'b': 2, 'a': 1, 'i': 1, 'c': 1})
# 升级:默认值是某一具体对象,如{"name":"","age":18}
def default_num():
return {"name":"","age":18}
default_dict = defaultdict(default_num)
default_dict["one"]
print(default_dict) # defaultdict(<function default_num at 0x00000152D9C4AE50>, {'one': {'name': '', 'age': 18}})
# 通过__miss__来实现该功能
# def __missing__(self, key): # real signature unknown; restored from __doc__
# """
# __missing__(key) # Called by __getitem__ for missing key; pseudo-code:
# if self.default_factory is None: raise KeyError((key,))
# self[key] = value = self.default_factory()
# return value
# """
# pass
5、deque
普通队列,先进先出FIFO
- 队列不能循环
- 不是迭代器,无法用for
TypeError: 'Queue' object is not iterable
- 也无法插入内容
双端队列,可以快速的从另外一侧追加和推出对象 - 可以从前拿,从后拿,不能从中间拿
- 从前添加,从后添加,可以通过索引的方式指定位置添加:即可中间加值
- 可迭代,可for循环
from collections import deque
user_deque=deque("baicao")
# def __init__(self, iterable=(), maxlen=None): # known case of _collections.deque.__init__
# """
# deque([iterable[, maxlen]]) --> deque object
#
# A list-like sequence optimized for data accesses near its endpoints.
# # (copied from class doc)
# """
# pass
print(user_deque) # deque(['b', 'a', 'i', 'c', 'a', 'o'])
# user_deque.append()
# user_deque.appendleft() # 最左边新增一个元素
# user_deque.extend()
# user_deque.extendleft() # 左边新增一个iterable
# user_deque.popleft() # 移除最左边的元素,并返回元素的值
# user_deque.pop()
# user_deque.clear()
# user_deque.insert(index, object)
# user_deque.reverse()
user2_deque = user_deque.copy() # deque的copy是深度拷贝,新的存储空间,彼此不影响
print(id(user2_deque),id(user_deque)) # 2792280947680 2792280945952
# user_deque.count()
# user_deque.index(value, start=None, stop=None) # 返回value对应的索引,没有报错
# 未旋转前,deque(['b', 'a', 'i', 'c', 'a', 'o'])
user_deque.rotate() # 将队列顺时针旋转n步,n默认1。若n为负,则向逆时针旋转
# def rotate(self, *args, **kwargs): # real signature unknown
# """ Rotate the deque n steps to the right (default n=1). If n is negative, rotates left. """
# pass
print(user_deque) # deque(['o', 'b', 'a', 'i', 'c', 'a'])
# __XX__ Python 魔法函数
from queue import Queue
# deque是线程安全的,GIL保护;list不是线程安全的
u_queue = Queue(10) # maxsize
u_queue.put("hello") # 一次放一个值
u_queue.put("world")
print(u_queue) # 只能查看内存地址 <queue.Queue object at 0x0000027E34A3FCD0>
print(u_queue.qsize()) # 查看队列的大小 # 2
# for i in u_queue: # TypeError: 'Queue' object is not iterable
# print(i)
print(u_queue.get()) # hello
print(u_queue.get()) # world
print(u_queue.get()) # 阻塞,没有数据可拿。直到给一个值才走
6、Counter
counter 自动化计数,返回dict类型;当计数相同时无序
from collections import Counter
# # 从一个可迭代对象创建
users = "12347891277398127"
user_counter = Counter(users) # 传参iterable
print(user_counter) # Counter({'7': 4, '1': 3, '2': 3, '3': 2, '8': 2, '9': 2, '4': 1})
# 空类
c = Counter()
print(c) # Counter()
# 从一个字典对象/可迭代对象创建
c = Counter({"name":"bai","age":17})
print(c) # Counter({'name': 'bai', 'age': 17})
# 从一组键值对创建
c = Counter(name="cao",age=18)
print(c) # Counter({'name': 'cao', 'age': 18})
# 从(k,v)格式的列表转化的dict创建
c = Counter(dict([("name","bai"),("age",5)]))
print(c) # Counter({'name': 'bai', 'age': 5})
c.clear() # 清空计数,即更新为空类,注意对象未删除
print(c) # Counter()
# 访问的键不存在时,返回0
print(c["name"]) # cao
print(c["c"]) # 0
# top n问题
data = user_counter.most_common(3) # 出现次数最多的前n个元素,并返回list类型
print(data) # [('1', 5), ('7', 5), ('2', 4)]
# 实现原理,返回Heap queues(堆结构)
# elements() 返回一个迭代器;元素被重复了多少次,在该迭代器中包含多少个。少于1的不被包含
c_list = list(c.elements())
print(c_list) # ['age', 'age', 'age', 'age', 'age']
print(list(c)) # 键转为list # ['age', 'n', 'a', 'm', 'e']
print(set(c)) # 键转为set # {'a', 'e', 'n', 'm', 'age'}
print(dict(c)) # 键值对转为dict # {'age': 5, 'n': -1, 'a': -1, 'm': -1, 'e': -1}
print(c.items()) # 转为(k,v)格式的列表 # dict_items([('age', 5), ('n', -1), ('a', -1), ('m', -1), ('e', -1)])
c+=Counter() # 移除0和负值 # 若存在值是非数字,则报错TypeError: 'str' object cannot be interpreted as an integer
print(c) # Counter({'age': 5})
user_counter.update("371486812") # 自动叠加,并更新Counter对象
print(user_counter) # Counter({'1': 5, '7': 5, '2': 4, '8': 4, '3': 3, '4': 2, '9': 2, '6': 1})
# 减少
c.subtract("name")
print(c) # Counter({'name': 'cao', 'age': 5, 'n': -1, 'a': -1, 'm': -1, 'e': -1})
# 删除 del
del c["name"]
print(c) # Counter({'age': 5, 'n': -1, 'a': -1, 'm': -1, 'e': -1})
7、OrderedDict
# OrderedDict
from collections import OrderedDict
user_dict=OrderedDict([("b",1),("a",2),("c",3)])
print(user_dict) # OrderedDict([('b', 1), ('a', 2), ('c', 3)])
user_dict = OrderedDict()
# user_dict = dict() # py3中dict默认有序的
user_dict["b"] = "bai"
user_dict["a"] = "abc"
user_dict["c"] = "cao"
print(user_dict) # OrderedDict([('b', 'bai'), ('a', 'abc'), ('c', 'cao')])
# 按照添加顺序
data = user_dict.pop("a") # 删除某一键值对,返回该键对应的值;未找到则报错
print(data) # abc
data2 = user_dict.popitem(last=False) # 默认删除最后一个,并返回键值对;last=False则删除最前面的
print(data2) # ('c', 'cao')
print(user_dict) # OrderedDict([('b', 'bai')])
user_dict.move_to_end("c",last=False) # 默认将指定键值对移动到最后;last=False则移动到最前面的
print(user_dict) # OrderedDict([('a', 'abc'), ('c', 'cao'), ('b', 'bai')])
有序字典需要注意:不同顺序的有序字典尽管值相同,但是顺序不同也会被认为是不同的有序字典
# user_dict2 = OrderedDict()
user_dict2 = dict() # py3中dict默认有序的
user_dict2["a"] = "abc"
user_dict2["b"] = "bai"
user_dict2["c"] = "cao"
print(user_dict == user_dict2) # False
# 若均是dict(),则输出True,是相同的
8、ChainMap
# ChainMap 访问多个dict,等同于一个
from collections import ChainMap
# 遍历多个dict的所有k-v
user_dict1 = {"a":"bai","b":"cao"}
user_dict2 = {"c":"ni","a":"hao"}
# 方法1:逐一dict,进行遍历for
# 方法2:多字典合并为一个字典(相同key仅保留了一个)
#方法2:ChainMap 迭代器,指向多数据
new_dict = ChainMap(user_dict1,user_dict2)
print(new_dict) # ChainMap({'a': 'bai', 'b': 'cao'}, {'c': 'ni', 'a': 'hao'})
for k,v in new_dict.items():
print(k,v) # 后面重复的key就会被去掉
网友评论