美文网首页python
py3笔记30:collections

py3笔记30:collections

作者: _百草_ | 来源:发表于2023-05-12 23:08 被阅读0次

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就会被去掉

参考

  1. python必学模块-collections
  2. python学习:collection模块的用法
  3. collection模块
  4. python中collection模块的简单介绍(附示例)

相关文章

网友评论

    本文标题:py3笔记30:collections

    本文链接:https://www.haomeiwen.com/subject/ublysdtx.html