将生成器转换为列表会覆盖Python中的值
我在Python 3.5中有一段代码,它实现了用于批处理潜在大缓冲数据的生成器:将生成器转换为列表会覆盖Python中的值,python,Python,我在Python 3.5中有一段代码,它实现了用于批处理潜在大缓冲数据的生成器: def batched_data(data, size=20): batch = [] for d in data:
def batched_data(data, size=20):
batch = []
for d in data:
batch.append(d)
if len(batch) == size:
yield batch
batch.clear()
yield batch
def buffered_data(data, bufminsize=10, bufmaxsize=20):
diter = iter(data)
buffer = collections.deque(next(diter) for _ in range(bufmaxsize))
while buffer:
yield buffer.popleft()
if len(buffer) < bufminsize:
buffer.extend(
next(diter) for _ in range(bufmaxsize - len(buffer)))
def batched_buffered_data(data, bufsize=100, batch=20):
yield from batched_data(
buffered_data(data, bufmaxsize=bufsize,
bufminsize=bufsize - batch),
size=batch)
但是,当我尝试使用列表理解或使用列表转换时,会发生以下情况:
In [353]: gen = batched_buffered_data(range(27), bufsize=10, batch=7)
In [354]: list(gen)
Out[354]:
[[21, 22, 23, 24, 25, 26],
[21, 22, 23, 24, 25, 26],
[21, 22, 23, 24, 25, 26],
[21, 22, 23, 24, 25, 26]]
我真的很困惑。一定涉及到某种可变元素,但我真的不知道这种行为背后的原因。将batch.clear更改为batch=[]应该可以解决这个问题。问题是批次列表在清除后仍然是对原始列表的引用。收益率似乎是有效的,因为它在下一个收益率上对元素进行变异之前,按照当时的显示打印一个列表。将它设置为每一个yield上的一个新列表会中断对上一个迭代的引用,因此不会出现别名
如果您仍然感到困惑,请使用原始代码检查此示例。清除:
输出:
[21, 22, 23, 24, 25, 26]
[21, 22, 23, 24, 25, 26]
[21, 22, 23, 24, 25, 26]
[21, 22, 23, 24, 25, 26]
将batch.clear更改为batch=[]应该可以解决此问题。问题是批次列表在清除后仍然是对原始列表的引用。收益率似乎是有效的,因为它在下一个收益率上对元素进行变异之前,按照当时的显示打印一个列表。将它设置为每一个yield上的一个新列表会中断对上一个迭代的引用,因此不会出现别名
如果您仍然感到困惑,请使用原始代码检查此示例。清除:
输出:
[21, 22, 23, 24, 25, 26]
[21, 22, 23, 24, 25, 26]
[21, 22, 23, 24, 25, 26]
[21, 22, 23, 24, 25, 26]
您应该将batch.clear更改为batch=[]
这是因为。清除列表,所有指向该列表的变量将变为[],否则batch=[]只需创建一个新列表并将其分配给batch您应该将batch.clear更改为batch=[]
这是因为。清除列表,所有指向该列表的变量将变为[],否则batch=[]只需创建一个新列表并将其分配给batch更改batch即可。清除到batch=[]应该可以解决此问题。它确实解决了此问题,但我仍然不知道它为什么会工作-生成器多次生成同一个列表。然后它修改该列表。这就是为什么您会得到4个相同的列表作为输出,因为它们实际上都是相同的列表。将batch.clear更改为batch=[]应该可以解决此问题。它确实解决了此问题,但我仍然不知道其确切的工作原因….:-生成器多次生成同一个列表。然后它修改该列表。这就是为什么您会得到4个相同的列表作为输出,因为它们实际上都是相同的列表。
In [353]: gen = batched_buffered_data(range(27), bufsize=10, batch=7)
In [354]: list(gen)
Out[354]:
[[21, 22, 23, 24, 25, 26],
[21, 22, 23, 24, 25, 26],
[21, 22, 23, 24, 25, 26],
[21, 22, 23, 24, 25, 26]]
result = []
gen = batched_buffered_data(range(27), bufsize=10, batch=7)
for g in gen:
result.append(g)
[print(x) for x in result]