python中的deque

动机

python内置类型中有list,其提供的pop和insert(append)方法,可以将其当作队列或栈使用,但由于其底层是数组实现,在左端插入或删除是O(n)复杂度。若需要频繁对双端处数据进行插入删除,就需要考虑其他数据结构了。

collections模块中提供deque
deque是双端队列(底层为双向链表),不需要像list一样动态增长存储空间
不支持切片
不支持in-place排序
必须由迭代器初始化
可变类型

常用方法

1.元素访问及相关方法

在左端操作专用方法
popleft()与appendleft(),支持extendleft、extend,这些与list相关方法类似
注意,此时pop()方法不能删除任意元素了,仅仅能移除最右端元素

dd = deque([1,4,3])
print( dd[1] )	# 可根据索引获取元素
del dd[1]		# 删除指定位置元素
print(dd[1])
dd.insert(1, 3)	# 根据索引插入元素
print(dd)
dd.remove(3)	# 删除第一个与给定值相同的元素,若不存在该元素,抛出ValueError
print(dd)
# 上述输出为
4
3
deque([1, 3, 3])
deque([1, 3])

Deques支持索引,但有趣的是,它不支持切片。链表并不能高效的实现切片操作

使用deque可以方便的实现栈和队列。

# 拼接
numbers = numbers + deque([5,6])    #
# 复制
numbers = numbers*2     #
# 指定范围搜索给定元素
print( numbers.index(5, 3, 7) )
# 统计value出现次数
print( numbers.count(5) )

index方法可实现指定范围搜索某个给定值,此外还有clear、reverse、copy等方法

2.其他操作

2.1 maxlen指定队列最长长度,若超过则从另一端删除。

four_numbers = deque([0, 1, 2, 3, 4], maxlen=4)	
print(four_numbers)
four_numbers.append(5)
print(four_numbers)
four_numbers.appendleft(6)
print(four_numbers)

如果不指定maxlen,其默认为None,即可无限增加

2.2 非空deque可调用rotate()方法
相当于循环右移,默认值为1,提供负值可实现循环左移

numbers = deque([0, 1, 2, 3, 4])
numbers.rotate()
print( numbers )	# deque([4, 0, 1, 2, 3])
numbers.rotate(-2)
print( numbers )    # deque([1, 2, 3, 4, 0])

deque线程安全性理解

Raymond Hettinger大佬原话

The deque’s append(), appendleft(), pop(), popleft(), and len(d) operations are thread-safe in CPython.

释放GIL

实现原理:因为有GIL的存在,其充当了锁的作用。当获取了GIL才能操作python对象或调用Python/C API函数。
python解释器每执行若干条python指令(缺省值100)后(或IO操作)会尝试做线程切换(释放GIL)
或者需要长期计算但不访问python对象的操作,zlib和hashlib模块,例如在内存缓冲区上操作的压缩或加密函数,也会释放GIL

注意上述指明是python指令,而在C函数中如果没有主动释放GIL,是不会有机会切走的

而deque这些操作底层是C函数,因此可以将这些操作看成原子操作。
参考:https://www.zhihu.com/question/52605823
https://docs.python.org/2/c-api/init.html#releasing-the-gil-from-extension-code

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
deque(双端队列)是Python标准库collections模块的一种数据结构,它可以在队列的两端进行添加和删除操作,因此可以用于实现栈和队列。 deque支持的操作包括: 1. append(x):在deque的右端添加元素x。 2. appendleft(x):在deque的左端添加元素x。 3. clear():清空deque。 4. count(x):返回deque元素x的个数。 5. extend(iterable):在deque的右端添加可迭代对象iterable的所有元素。 6. extendleft(iterable):在deque的左端添加可迭代对象iterable的所有元素,注意添加顺序与iterable的顺序相反。 7. pop():删除并返回deque右端的元素。 8. popleft():删除并返回deque左端的元素。 9. remove(x):删除deque第一个值为x的元素,如果没有找到则抛出ValueError异常。 10. reverse():将deque的元素反转。 11. rotate(n=1):将deque的元素向右移动n步,如果n为负数则向左移动。移动的元素会从deque的一端移动到另一端,因此deque的长度不变。 使用deque需要先导入collections模块: ``` from collections import deque ``` 然后可以通过以下方式创建一个deque对象: ``` d = deque() ``` 也可以通过传入一个可迭代对象来初始化deque: ``` d = deque([1, 2, 3]) ``` 使用deque的操作与列表类似,例如: ``` d.append(4) d.appendleft(0) d.extend([5, 6]) d.extendleft([-1, -2]) d.pop() d.popleft() d.remove(3) d.reverse() d.rotate(2) ``` 注意,由于deque支持在两端进行添加和删除操作,因此它的时间复杂度比列表更优秀,特别是在涉及到大量添加和删除操作的场景

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值