美文网首页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