python技巧

collections模块

2018-09-05  本文已影响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}
上一篇 下一篇

猜你喜欢

热点阅读