zoukankan      html  css  js  c++  java
  • python常用模块——collections

    好久没学习了,简单了解下

    Ⅰ、namedtuple

    1.1 简单回顾一下tuple

    tuple是一个不可变的可迭代对象

    ①可迭代
    In [1]: test_tuple = (1,2,3,4,5)
    
    In [2]: for i in test_tuple:
       ...:     print(i)
       ...:     
    1
    2
    3
    4
    5
    
    ②不可变
    In [3]: test_tuple[0] = 5
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-3-8e5f1b05e43e> in <module>()
    ----> 1 test_tuple[0] = 5
    
    TypeError: 'tuple' object does not support item assignment
    
    不可变指的是其中的元素不可变
    In [4]: test_tuple = (6,7,8)
    
    其元素不可变也不是绝对的
    In [5]: test_tuple = (1,[2,3])
    
    In [6]: test_tuple[1].append(4)
    
    In [7]: print(test_tuple)
    (1, [2, 3, 4])
    
    ③拆包
    In [8]: user_tuple = ("allen", 29, 175)
    
    In [9]: name, age, height = user_tuple
    
    In [10]: print(name, age, height)
    allen 29 175
    
    In [11]: name, *other = user_tuple
    
    In [12]: print(name, other)
    allen [29, 175]
    

    1.2 tuple对比list的优势

    • 性能更好
    • 线程安全
    • 拆包特性
    • 可以作为dict的key(可hash),如下:
    In [14]: user_info_dict = {}
    
    In [15]: user_info_dict[user_tuple] = "allen"
    
    In [16]: user_info_dict
    Out[16]: {('allen', 29, 175): 'allen'}
    
    In [17]: user_info_dict[[1,2,3]] = "Kobe"
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-17-a32e731657ac> in <module>()
    ----> 1 user_info_dict[[1,2,3]] = "Kobe"
    
    TypeError: unhashable type: 'list'
    

    对应C语言来说,tuple对应的是struct,而list对应的是array

    1.3 nametuple创建一个User类

    In [23]: from collections import namedtuple
    
    In [24]: User = namedtuple("User", ["name", "age", "height", "edu"])
    
    In [25]: user = User(name="Allen", age=29, height=175, edu="master")
    
    In [26]: print(user.age, user.name, user.height, user.edu)
    29 Allen 175 master
    
    # 加一个字段
    In [29]: user_tuple = ("Allen", 29, 175)
    
    In [30]: user = User(*user_tuple, "master")
    # user = User("Allen", 29, 175, "master")
    
    In [31]: user
    Out[31]: User(name='Allen', age=29, height=175, edu='master')
    
    In [33]: user_dict = {"name":"allen","age":19,"height":175}
    
    In [34]: user = User(**user_dict, edu="master")
    
    In [35]: user
    Out[35]: User(name='allen', age=19, height=175, edu='master')
    
    

    1.4 看两个方法

    • _make() 传入一个可迭代对象初始化namedtuple,灵活性不如前面直接传参
    In [36]: user_tuple = ("Allen", 29, 175, "edu")
    
    In [37]: user = User._make(user_tuple)
    
    In [38]: user_list = ["Allen", 29, 175, "edu"]
    
    In [39]: user = User._make(user_list)
    
    In [42]: user_dict = {"name":"allen","age":19,"height":175, "edu":"master"}
    
    In [43]: user = User._make(user_dict)
    
    • _asdict() 将tuple转为dict
    - In [46]: user = User(name="Allen", age=29, height=175, edu="master")
    
    In [47]: user_info_dict = user._asdict()
    
    In [48]: user_info_dict
    Out[48]: 
    OrderedDict([('name', 'Allen'),
                 ('age', 29),
                 ('height', 175),
                 ('edu', 'master')])
    
    tips:namedtuple也可以拆包,如下
    In [49]: name, age, *other =user
    
    In [50]: print(name, age, other)
    Allen 29 [175, 'master']
    

    Ⅱ、defaultdict

    需求:统计一个列表中每个元素的个数

    • 老式方法
    In [70]: a = [1,2,3,2,3,2,3,2,4,4,4,5]
    
    In [71]: c_dict = {}
    
    In [72]: for i in a:
        ...:     if i not in c_dict:
        ...:         c_dict[i] = 1
        ...:     else:
        ...:         c_dict[i] += 1
        ...:         
    
    In [73]: c_dict
    Out[73]: {1: 1, 2: 4, 3: 3, 4: 3, 5: 1}
    
    • 另一个方法:
    In [63]: a = [1,2,3,2,3,2,3,2,4,4,4,5]
    
    In [64]: c_dict = {}
    
    In [65]: for i in a:
        ...:     c_dict.setdefault(i,0)
        ...:     c_dict[i] += 1
        ...:     
    
    In [66]: c_dict
    Out[66]: {1: 1, 2: 4, 3: 3, 4: 3, 5: 1}
    
    • 最好的方法
    In [77]: from collections import defaultdict
    
    In [78]: c_dict = defaultdict(int)
    
    In [79]: a = [1,2,3,2,3,2,3,2,4,4,4,5]
    
    In [80]: for i in a:
        ...:     c_dict[i] += 1 #当key不存在时不会报错,绑一个0
        ...:     
    
    In [81]: c_dict
    Out[81]: defaultdict(int, {1: 1, 2: 4, 3: 3, 4: 3, 5: 1})
    

    弄个自定义的带嵌套的玩一下

    In [82]: def gen_default():
        ...:     return {
        ...:         "name":"",
        ...:         "nums":0
        ...:     }
        ...: 
        ...: 
    
    In [83]: default_dict = defaultdict(gen_default)
    
    In [85]: default_dict["test"]
    Out[85]: {'name': '', 'nums': 0}
    

    Ⅲ、deque

    deque GIL是线程安全的,list不是
    deque叫做双端队列,那我们就得和list一起看,先看下list

    In [86]: a_list = [1,2]
    
    In [87]: t = a_list.pop()
    
    In [88]: print(t, a_list)
    2 [1]
    可以看到最后一个元素被弹出来了
    

    3.1 弄最左边

    • 插左边
    In [94]: from collections import deque
    
    In [95]: a_deque = deque([1, [2, 3], 4])
    
    In [96]: a_deque.appendleft(5)
    
    In [97]: a_deque
    Out[97]: deque([5, 1, [2, 3], 4])
    
    • 弹左边
    In [97]: a_deque
    Out[97]: deque([5, 1, [2, 3], 4])
    
    In [98]: a_deque.popleft()
    Out[98]: 5
    

    3.2 copy()

    In [99]: a = deque([1,[2, 3], 4])
    
    In [100]: b = a.copy()
    
    In [101]: print(a, b)
    deque([1, [2, 3], 4]) deque([1, [2, 3], 4])
    
    In [102]: print(id(a), id(b))
    139908896451392 139908896452328
    
    In [103]: b[1].append(5)
    
    In [104]: print(a, b)
    deque([1, [2, 3, 5], 4]) deque([1, [2, 3, 5], 4])
    由上可知,这种copy是浅拷贝
    
    • 深拷贝怎么弄?
      deque本身没提供,需要用到copy这个包
    In [106]: import copy
    
    In [107]: a = deque([1,[2, 3], 4])
    
    In [108]: b = copy.deepcopy(a)
    
    In [109]: b[1].append(5)
    
    In [110]: print(a, b)
    deque([1, [2, 3], 4]) deque([1, [2, 3, 5], 4])
    

    3.3 extend()

    In [111]: a = deque([1,2,3])
    
    In [112]: b = deque([4,5,6])
    
    In [113]: a.extend(b)
    
    In [114]: a
    Out[114]: deque([1, 2, 3, 4, 5, 6])
    
    注意:这是直接在a上动态扩容,并不会返回一个新的列表,所以c = a.extend(b)是错的
    

    3.4 其他方法

    In [114]: a
    Out[114]: deque([1, 2, 3, 4, 5, 6])
    
    In [115]: a.insert(1,888)
    
    In [116]: a.reverse()
    
    In [117]: print(a)
    deque([6, 5, 4, 3, 2, 888, 1])
    
    extendleft(),index(),count(),clear()等这里就不演示了
    

    Ⅳ、Counter()

    In [122]: from collections import Counter
    
    In [123]: tmp = "132531321059823"
    
    In [124]: t_count = Counter(tmp)
    
    In [125]: t_count
    Out[125]: Counter({'1': 3, '3': 4, '2': 3, '5': 2, '0': 1, '9': 1, '8': 1})
    
    # 找top
    In [126]: t_count.most_common(2)
    Out[126]: [('3', 4), ('1', 3)]
    

    两个串合起来统计

    In [126]: t_count.most_common(2)
    Out[126]: [('3', 4), ('1', 3)]
    
    In [127]: t_count.update("3311")
    
    In [128]: t_count.most_common(2)
    Out[128]: [('3', 6), ('1', 5)]
    
    再来一把
    In [129]: tmp2 = "3311"
    
    In [130]: t_count.update(tmp2)
    
    In [131]: t_count.most_common(2)
    Out[131]: [('3', 8), ('1', 7)]
    

    Ⅴ、OrderedDict

    字典中的元素本来是无序的,下面这个用了OrderedDict,有序了(添加顺序),python2中和原来的Dict对比就能看出区别,3看不出来

    In [141]: from collections import OrderedDict
    
    In [142]: t_dict = OrderedDict()
    
    In [143]: t_dict["b"] = "2b"
    
    In [144]: t_dict["a"] = "1a"
    
    In [145]: t_dict["c"] = "3c"
    
    In [146]: t_dict
    Out[146]: OrderedDict([('b', '2b'), ('a', '1a'), ('c', '3c')])
    

    5.1 一些方法

    In [146]: t_dict
    Out[146]: OrderedDict([('b', '2b'), ('a', '1a'), ('c', '3c')])
    
    In [147]: print(t_dict.pop("a"))
    1a
    
    In [149]: print(t_dict.popitem())
    ('c', '3c')
    
    pop()必须指定key,popitem()不用,默认弹出最后一组key:value
    

    把指定元素放到最后

    In [155]: t_dict
    Out[155]: OrderedDict([('a', '1a'), ('c', '3c'), ('b', '2b')])
    
    In [156]: t_dict.move_to_end("a")
    
    In [157]: t_dict
    Out[157]: OrderedDict([('c', '3c'), ('b', '2b'), ('a', '1a')])
    

    Ⅵ、ChainMap

    实现访问多个dict就像访问一个dict一样(在多个字典上套一个迭代器)

    In [160]: from collections import ChainMap
    
    In [161]: dt1 = {"a":"bb1","b":"bb2"}
    
    In [162]: dt2 = {"a":"bb1","b":"bb2"}
    
    In [163]: n_dt = ChainMap(dt1, dt2)
    
    In [164]: n_dt
    Out[164]: ChainMap({'a': 'bb1', 'b': 'bb2'}, {'a': 'bb1', 'b': 'bb2'})
    
    # 加一个新的字典
    In [165]: n_dt = n_dt.new_child({"e":"ee5"})
    
    In [166]: n_dt
    Out[166]: ChainMap({'e': 'ee5'}, {'a': 'bb1', 'b': 'bb2'}, {'a': 'bb1', 'b': 'bb2'})
    
    # 将字典变成列表(maps指向原来的字典,并不是新生成的一个数据)
    In [168]: n_dt.maps
    Out[168]: [{'e': 'ee5'}, {'a': 'bb1', 'b': 'bb2'}, {'a': 'bb1', 'b': 'bb2'}]
    
    In [171]: n_dt.maps[1]["a"] = "ahaha"
    
    In [173]: for key, value in n_dt.items():
         ...:     print(key, value)
         ...:     
    a ahaha
    b bb2
    e ee5
    
  • 相关阅读:
    (三)OpenCV-Python学习—图像平滑
    (二)OpenCV-Python学习—对比度增强
    (一)OpenCV-Python学习—基础知识
    mongodb的安装及使用
    python操作MySQL数据库的三个模块
    mysql数据库学习二
    (八)爬虫之js调试(登陆知乎)
    经典Paxos算法笔记
    ThreadPoolExecutor源码解读
    FutureTask源码解读
  • 原文地址:https://www.cnblogs.com/---wunian/p/9437928.html
Copyright © 2011-2022 走看看