将生成器转换为列表会覆盖Python中的值

将生成器转换为列表会覆盖Python中的值,python,Python,我在Python 3.5中有一段代码,它实现了用于批处理潜在大缓冲数据的生成器: def batched_data(data, size=20): batch = [] for d in data:

我在Python 3.5中有一段代码,它实现了用于批处理潜在大缓冲数据的生成器:

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]