gpt4 book ai didi

python - 使用生成器进行列表理解

转载 作者:行者123 更新时间:2023-11-30 23:31:30 25 4
gpt4 key购买 nike

我使用生成器生成一些列表。但是,它并不像我预期的那样工作。我首先使用 numgen1 来生成列表,但它无法正常工作。我切换到 numgen2,它可以正确地给我我想要的东西。但 numgen1 和 numgen2 基本上是相同的(至少我认为),为什么它们的行为如此不同?有人可以给我一些解释吗?

def numgen1(start, end, delta):
curr=start
while curr[1] < end[1] or curr[2]<end[2]:
yield curr
curr[2] += delta


print 'Output1: ', [ i for i in numgen1([1,1,1],[1,1,5],1)]

def numgen2(start, end, delta):
curr=start
while curr[1] < end[1] or curr[2]<end[2]:
yield [curr[0], curr[1], curr[2]]
curr[2] += delta


print 'Output2: ', [ i for i in numgen2([1,1,1],[1,1,5],1)]

这是输出。

Output1:  [[1, 1, 5], [1, 1, 5], [1, 1, 5], [1, 1, 5]]
Output2: [[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4]]

后续问题:

读完 unutbu 的答案后,我又编写了一个生成器,用于测试 unutbu 所说的内容。但生成器的行为并不像 unutbu 所说的那样。我很困惑生成器是否产生指针或值的副本。

def numgen3(start, end, delta):
curr=start
while curr<end:
yield curr
curr += delta

print list(numgen3(1,10,1))

这是输出。[1,2,3,4,5,6,7,8,9]

这次我尝试生成一些数字而不是一些列表。但为什么列表中的元素不是全部都是 9 呢?我没有创建新数字,只是产生相同的数字(curr)。我预计 numgen3 的结果应该与 numgen1 类似。

最佳答案

curr 是一个列表。 curr[2] += delta 正在就地修改列表。

当您生成 curr 时,您会一遍又一遍地生成相同的列表。当您打印 Output1 时,您会看到同一个列表被打印了很多次。

当您产生[curr[0], curr[1], curr[2]]时,您正在生成一个新列表。因此,当您打印 Output2 时,您会看到不同的值。

<小时/>

请注意修改 curr 如何影响 result 中的所有项目,因为 result 是一个包含 3 个项目的列表,每个列表都相同curr:

curr = [0,0,0]
result = [curr for i in range(3)]
print(result)
# [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

curr[2] = 100
print(result)
# [[0, 0, 100], [0, 0, 100], [0, 0, 100]]
<小时/>

您可以通过生成 list(curr) 来“修复”numgen1,因为 list(curr) 返回一个新列表,其元素与在 curr 中(即“浅拷贝”):

def numgen1(start, end, delta):
curr=start
while curr[1] < end[1] or curr[2]<end[2]:
yield list(curr)
curr[2] += delta

print 'Output1: ', [ i for i in numgen1([1,1,1],[1,1,5],1)]

产量

Output1:  [[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4]]
<小时/>

关于numgen3:

def numgen3(start, end, delta):
curr=start
while curr<end:
yield curr
curr += delta

print list(numgen3(1,10,1))

它有助于在心理上区分可变值和不可变值。列表是可变的,诸如int之类的数字是不可变的。

列表是容器。您可以更改其内容,而无需更改对容器的引用。因此,curr 是一个列表,curr[2] += delta 改变索引 2 处的内容,但 yield curr 产生完全相同的列表。

numgen3中,curr是一个不可变的intcurr += deltacurr 分配给新的不可变 int。它不再引用同一个对象。 yield curr 产生该值。这些不同的值在列表理解中累积,因此您会看到包含不同值的结果。

<小时/>

这里是关于就地修改列表含义的另一种观点:如果列表的内容发生变化,则修改就地完成,而列表的内容发生变化。列表本身的内存地址不会改变。

id(obj) 返回对象obj的内存地址。请注意,修改 curr[2] 不会更改 currid:

In [162]: curr = [0,0,0]

In [163]: id(curr)
Out[163]: 196192940

In [164]: curr[2] += 1

In [165]: curr
Out[165]: [0, 0, 1]

In [166]: id(curr)
Out[166]: 196192940

将其与递增分配给 int 的变量时发生的情况进行比较:

In [191]: curr = 1

In [192]: id(curr)
Out[192]: 150597808

In [193]: curr += 1

In [194]: id(curr)
Out[194]: 150597796

这里,curr 没有被就地修改。 curr 只是被重定向以引用新内存地址处的新值。

关于python - 使用生成器进行列表理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19876823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com