collections模块

作者: 陆_志东 | 来源:发表于2018-09-05 18:32 被阅读0次

    collections是python内建的集合模块,提供了许多有用的集合类

    nametuple

    将元祖由索引下标调用改为由像类调用属性那样调用
    示例:
    普通元祖的调用方式

    tuple1 = (1, 2)
    print(tuple1[0])  # 普通元祖通过下标获取数据
    >>1
    print(tuple1[1])
    >>2
    

    nametuple的调用方式:以定义一个点Point为例,也是python源码示例

    from collections import namedtuple
    
    Point = namedtuple("Point",["x","y"])
    tp1 = Point(1,2)
    print(Point.__doc__)  # Point(x, y)
    # 转换为nametuple之后,依然可以像元祖那样调用,相当于多了一种调用的方式
    print(tp1[0])  # 1
    print(tp1.x)   # 1
    
    print(tp1[1])  # 2
    print(tp1.y)   # 2
    x, y = tp1  # tuple unpack 元祖解包
    print(x,y)  # 1 2
    
    dict_tp1 = tp1._asdict()  # convert nametuple to OrderedDict
    print(dict_tp1)  #  OrderedDict([('x', 1), ('y', 2)])
    print(dict_tp1["x"])  # 1
    
    tp3 = tp1._replace(x=100)  # 元祖不可变,所以这里实际是生成了一个新的对象返回,类型字符串的替换
    print(tp3.x)  # 100
    
    dict1 = {"x":10,"y":20}
    tp2 = Point(**dict1)  # pass parameter with unpack from a dictionary
    print(tp2) # Point(x=10, y=20)
    print(tp2.x)  # 10
    

    deque双端队列(列表)

    使用list存储数据时,利用下标索引访问很快,但是插入和删除元素就很慢了.因为list的数据结构是线性表结构,每插入一个数据,该插入点之后的数据都要往后迁移一格(为了保证有序性),所以效率会低,deque是为了高效实现插入和删除操作的双向列表,适用于队列和栈

    from collections import deque
    
    list1 = [0,1,2,3,1,1]
    deq = deque(list1)
    print(deq)  # deque([0, 1, 2, 3, 1, 1])
    print(deq[1])  # 1
    deq.append(4)
    deq.appendleft(-1)
    print(deq)  # deque([-1, 0, 1, 2, 3, 1, 1, 4])
    print(deq.count(1)) # 3
    deq.extend([5, 6])  # deque 也可以拼接普通的列表
    deq.extendleft(deque([-3,-2]))  # 拼接deque列表
    print(deq)  # deque([-2, -3, -1, 0, 1, 2, 3, 1, 1, 4, 5, 6])
    pop_right1 = deq.pop()  # 删除最后一个
    pop_left1 = deq.popleft() # 删除第一个
    print(pop_left1,pop_right1,deq)  # -2 6 deque([-3, -1, 0, 1, 2, 3, 1, 1, 4, 5])
    # 普通列表支持指定索引删除,deque不支持,下面写的方式会报错
    # pop_index = deq.pop(2)  # 注意不能这样写,普通列表可以指定索引删除,但是deque不可以
    
    # 指定元素删除
    num = deq.remove(0)  # 注意remove 不像pop 那样有返回值.remove操作不返回结果
    print(num,deq) # None deque([-3, -1, 1, 2, 3, 1, 1, 4, 5])
    
    # 因为deque是可变数据类型,所以reverse操作是直接修改原数据,而不是生成新数据返回
    reverse_deque = deq.reverse()
    print(reverse_deque,deq)  # None deque([5, 4, 1, 1, 3, 2, 1, -1, -3])
    
    # rotate旋转操作(也可以理解为平移,超出边界后从头挪到尾或从尾挪到头),接收一个参数n,
    # 当n为整数时,所有数据整体向右平移n个位置.n为负数,向左平移n个位置
    # deque可变类型, rotate操作同样时改变原数据,非生成新数据返回
    rotate_deque = deq.rotate(1)
    print(rotate_deque,deq)  # None deque([-3, 5, 4, 1, 1, 3, 2, 1, -1])
    
    # clear 清空deque
    # clear 清空deque
    print(deq.clear(),deq)  # None deque([])
    print(len(deq)) # 0
    

    defaultdict

    defaultdict在初始化的时候,默认传递None,即取不存在的key时,会抛出keyerror,想要key不存在时,需要传递一个可调用的参数进去,这里我们选择了使用匿名函数(写法简洁)当做参数传递,普通字典的get方法也可以达到返回默认值的情况

    from collections import defaultdict
    dict1 = defaultdict(lambda :"haha")
    print(dict1["a"])  # haha
    dict1["a"] = 11
    print(dict1["a"])  # 11
    
    # 普通dict
    dict1 = {"a":1}
    print(dict1.get("a"))  # 1
    print(dict1.get("b"))  # None
    print(dict1.get("b","haha"))  # haha
    

    OrderDict

    OrderDict不会改变插入字典的键值对的顺序,其他功能和普通字典一样

    from collections import OrderedDict
    list1 = [(1,2),(2,3),(3,4),(4,5),(5,6),(6,7)]
    dict1 = OrderedDict(list1)
    print(dict1)
    >>OrderedDict([(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7)])
    print(dict1.popitem())  # last default True;default pop last item ; while last is False,the first item will be pop
    >>(6, 7)
    print(dict1.popitem(last=False))  # the first item will be pop, return tuple
    >>(1, 2)
    print(dict1.pop(3))  # return the key corresponding to the value
    >>4
    print(dict1)
    >>OrderedDict([(2, 3), (4, 5), (5, 6)])
    

    利用有序字典创建一个FIFO(先进先出)的字典队列,超出上限,删除第一个元素

    from collections import OrderedDict
    
    
    class FIFO_dict(OrderedDict):
        def __init__(self,max_value,*args,**kwargs):
            super(FIFO_dict, self).__init__(*args,**kwargs)
            self.max_value = max_value
    
        def __setitem__(self, key, value):
            current_len = len(self)
            is_need_update = 0 if key not in self else 1
            is_need_pop_left_item = 1 if current_len - is_need_update >= self.max_value else 0
            if is_need_update:  # is_need_update 为 1 的时候 is_need_pop_left_item 一定会是0
                self.pop(key)
            if is_need_pop_left_item:
                self.popitem(last=False)
            super(FIFO_dict, self).__setitem__(key,value)
    
        def get_first(self):
            return self.popitem(last=False)
    
    
    fifo1 = FIFO_dict(3)
    fifo1[0] = 0
    fifo1[1] = 1
    fifo1[2] = 2
    print(fifo1)
    >>FIFO_dict([(0, 0), (1, 1), (2, 2)])
    fifo1[3] = 3
    print(fifo1)
    >>FIFO_dict([(1, 1), (2, 2), (3, 3)])
    fifo1[2] = 4
    print(fifo1)
    >>FIFO_dict([(1, 1), (3, 3), (2, 4)])
    print(fifo1.get_first())
    >>(1, 1)
    

    Counter

    Counter是一个计数器,可以统计放入元素出现的次数

    from collections import Counter
    
    str1 = "adawq112eadd"
    c1 = Counter()
    for s in str1:
        c1[s] = c1[s] + 1
    print(c1)
    >>Counter({'d': 3, 'a': 3, '1': 2, 'q': 1, '2': 1, 'e': 1, 'w': 1})
    

    自己实现一个Counter

    class MyCounter(object):
        def __init__(self):
            self.map = dict()
    
        def set_ele(self,key):
            if key not in self.map:
                self.map[key] = 0
            self.map[key] += 1
    
        def __repr__(self):
            return "{}".format(self.map)
    
    str2 = "adawq112eadd"
    mycounter  = MyCounter()
    for data in str2:
        mycounter.set_ele(data)
    print(mycounter)
    >>{'q': 1, '2': 1, 'e': 1, 'd': 3, 'a': 3, 'w': 1, '1': 2}
    

    相关文章

      网友评论

        本文标题:collections模块

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