python 双端队列的理解
python deque understanding
我在 Whosebug 中发现了一些代码,这些代码提出了两个关于 deque
工作方式的问题。我没有足够的声誉来问 "in situ",因此这个问题:
from collections import deque
from itertools import islice
def sliding_window(iterable, size=2, step=1, fillvalue=None):
if size < 0 or step < 1:
raise ValueError
it = iter(iterable)
q = deque(islice(it, size), maxlen=size)
if not q:
return # empty iterable or size == 0
q.extend(fillvalue for _ in range(size - len(q))) # pad to size
while True:
yield iter(q) # iter() to avoid accidental outside modifications
q.append(next(it))
q.extend(next(it, fillvalue) for _ in range(step - 1))
代码计算给定大小在序列上的滑动 window。
不懂的步骤先:
q = deque(islice(it, size), maxlen=size)
这里maxlen
有什么用?是不是 islice
总是要输出一个最大长度为 size
的迭代器?
第二个:
yield iter(q) # iter() to avoid accidental outside modifications
为什么我们需要转换为可迭代以避免"accidental outside modifications"?
要回答问题的第一部分,设置 maxlen 将使双端队列在添加项目时不超过该大小 - 旧项目将被丢弃。
为了回答问题的第二部分,Python 中的所有内容均通过引用传递。因此,在上面的情况下 generator q
是对函数持有的原始双端队列的引用,因此任何可能修改双端队列的方法都会破坏生成的原始算法。当你用 iter()
包围 q
时,你有效地产生了一个迭代器。您可以从迭代器中获取元素(读取),但不能更改元素本身或修改它们的顺序(不允许写入)。因此,防止意外损坏发电机内部的容器是一个很好的做法。
我在 Whosebug 中发现了一些代码,这些代码提出了两个关于 deque
工作方式的问题。我没有足够的声誉来问 "in situ",因此这个问题:
from collections import deque
from itertools import islice
def sliding_window(iterable, size=2, step=1, fillvalue=None):
if size < 0 or step < 1:
raise ValueError
it = iter(iterable)
q = deque(islice(it, size), maxlen=size)
if not q:
return # empty iterable or size == 0
q.extend(fillvalue for _ in range(size - len(q))) # pad to size
while True:
yield iter(q) # iter() to avoid accidental outside modifications
q.append(next(it))
q.extend(next(it, fillvalue) for _ in range(step - 1))
代码计算给定大小在序列上的滑动 window。 不懂的步骤先:
q = deque(islice(it, size), maxlen=size)
这里maxlen
有什么用?是不是 islice
总是要输出一个最大长度为 size
的迭代器?
第二个:
yield iter(q) # iter() to avoid accidental outside modifications
为什么我们需要转换为可迭代以避免"accidental outside modifications"?
要回答问题的第一部分,设置 maxlen 将使双端队列在添加项目时不超过该大小 - 旧项目将被丢弃。
为了回答问题的第二部分,Python 中的所有内容均通过引用传递。因此,在上面的情况下 generator q
是对函数持有的原始双端队列的引用,因此任何可能修改双端队列的方法都会破坏生成的原始算法。当你用 iter()
包围 q
时,你有效地产生了一个迭代器。您可以从迭代器中获取元素(读取),但不能更改元素本身或修改它们的顺序(不允许写入)。因此,防止意外损坏发电机内部的容器是一个很好的做法。