每日一包 - Collections.deque

240 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

介绍

deque 也是 collections模块中提供的用来替代 list 的一个选择,deque 是一个双端队列(对堆栈和队列的概括),可以快速的从另外一侧追加和删除对象,相对于Python内置的list来讲,对list的数据插入和删除进行了优化,支持从双端队列的任何一侧进行线程安全、内存高效的追加和弹出操作。

使用

deque对象

使用deque生成双端队列对象时,数据可以来自一个可迭代对象,可以不指定数据,得到的就是一个空的deque对象。

另外还有一个maxlen参数,如果未指定,默认值是None,表示双端队列可以增长至任意长度,如果指定了该参数的话,一旦达到最大长度,再向队列中添加新的对象时,另一端就会将多出的数量的对象从队列中删除。

from collections import deque
​
​
d = deque("abcde", maxlen=5)
​
print(d)  # deque(['a', 'b', 'c', 'd', 'e'], maxlen=5)
​
d.append("f")
print(d)  # deque(['b', 'c', 'd', 'e', 'f'], maxlen=5)
​
​

append(x)

从双端队列的右侧添加元素x到队列中,和list 对象的append方法类似。

from collections import deque
​
​
d = deque("abcde")
print(d)  # deque(['a', 'b', 'c', 'd', 'e'])
​
d.append("f")
print(d)  # deque(['a', 'b', 'c', 'd', 'e', 'f'])

appendleft(x)

从双端队列的左侧添加元素x到队列中。

d = deque("abcde")
print(d)  # deque(['a', 'b', 'c', 'd', 'e'])
​
d.appendleft("f")
print(d)  # deque(['f', 'a', 'b', 'c', 'd', 'e'])

clear()

移除所有元素,deque对象的长度变成0.

d = deque("abcde")
print(d)  # deque(['a', 'b', 'c', 'd', 'e'])
​
d.clear()
print(d)  # deque([])

copy()

通过copy方法复制一个deque对象,属于浅拷贝。

d = deque([1, 2, [1, 2]])
print(d)  # deque([1, 2, [1, 2]])
​
d1 = d.copy()
print(d1)  # deque([1, 2, [1, 2]])

count(x)

返回deque对象中x元素的个数。

d = deque("aabbccdd")
print(d.count("a"))  # 2

extend(iterable)

将可迭代对象中每个元素从deque对象的右侧进行扩展。

d = deque("aabbccdd")
d.extend([1, 2])
print(d)  # deque(['a', 'a', 'b', 'b', 'c', 'c', 'd', 'd', 1, 2])

extendleft(iterable)

将可迭代对象中每个元素从deque对象的左侧进行扩展。

d = deque("aabbccdd")
d.extendleft([1, 2])
print(d)  # deque([2, 1, 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'])

上述代码的原理类似于,将可迭代对象进行for循环,得到的每个元素进行d.append()操作。

index

返回x在deque中的位置也就是x的索引,返回的是第一个x的索引,如果找不到则会抛出ValueError

d = deque("aabbccdd")
print(d.index("b"))  # 2

insert(index, x)

将元素x插入到deque对象的index位置上,如果插入数据会导致一个限制长度的deque超出maxlen的话就会引发IndexError

d = deque("abc", maxlen=4)
d.insert(0, "d")
print(d)  # deque(['d', 'a', 'b', 'c'], maxlen=4)
d.insert(3, "e")  # IndexError: deque already at its maximum size

pop

移除deque对象中最右侧的元素并返回该值,如果deque中没有元素则会抛出IndexError

d = deque("abc", maxlen=4)
res = d.pop()
print(res)  # c

popleft

移除deque对象中最左侧的元素并返回该值,如果deque中没有元素则会抛出IndexError

d = deque("abc", maxlen=4)
res = d.pop()
print(res)  # a

remove(val)

根据元素值删除,删除找到的第一个元素,如果元素不存在则抛出IndexError

a = deque('abca')
a.remove('a')
a
deque(['b', 'c', 'a'])

reverse

将deque进行排序,默认是逆序,按照ASCII从大到小的顺序。

d = deque("abcACB")
d.reverse()
print(d)  # deque(['B', 'C', 'A', 'c', 'b', 'a'])

rotate(n)

n>=1时向右循环移动n步,当n<0时,向左循环引动n步。

向右循环1步等价于d.appendleft(d.pop()),向左循环一步等价于d.append(d.popleft())

# 向右
d = deque("abcACB")
d.rotate(1)
print(d)  # deque(['B', 'a', 'b', 'c', 'A', 'C'])

# 向左
d = deque("abcACB")
d.rotate(-1)
print(d)  # deque(['b', 'c', 'A', 'C', 'B', 'a'])

其他方法

除了上面的这么多方法之外,deque还支持for循环、len(d)、深浅拷贝、成员检测in以及通过索引下标d[0]方式取值等,但是deque不支持切片操作。

d = deque("abcACB")
print(len(d))
for i in d:
    print(i)
print(d[-1])

总结

deque在某些方面有点类似于Python内置的list,但是要比Python的list更加灵活,但是也不是任何时候deque都是更加合适的,还是需要根据实际情况选择使用。