[英]Python strange behavior with enumerate
我知道我不应该在循环中修改列表,但出于好奇,我想知道为什么以下两个示例之间的迭代次数不同。
例1:
x = [1, 2, 3, 4, 5]
for i, s in enumerate(x):
del x[0]
print(i, s, x)
例2:
x = [1,2,3,4,5]
for i, s in enumerate(x):
x = [1]
print(i, s, x)
示例1仅运行3次,因为当i==3
, len(x)==2
。
即使len(x)==1
示例2也运行5次。
所以我的问题是, enumerate
是否在循环开始时生成(index, value)
对的完整列表并迭代它? 或者它们是在循环的每次迭代中生成的?
在第一个示例中,您实际上正在修改正在迭代的列表。
另一方面,在第二种情况下,您只是将新对象分配给名称x
。 但是,循环迭代的对象不会改变。
有关Python中名称和变量的更详细说明,请查看http://foobarnbaz.com/2012/07/08/understanding-python-variables/ 。
enumerate()返回一个迭代器或一些支持迭代的其他对象。 enumerate()返回的迭代器的__next __()方法返回一个包含count的元组(从start开始,默认为0)和迭代迭代得到的值。
__next __()返回容器中的下一个项目。 如果没有其他项,请提高StopIteration
异常。
enumerate()是否在循环开始时生成(索引,值)对的完整列表并迭代它? 或者它们是在循环的每次迭代中生成的?
因此, enumerate()
返回一个迭代器,并且在每次迭代时, __next__()
检查是否还有其他项。 enumerate()
不会在循环开头创建完整列表。
正如@Wisperwind所提到的那样,在你的第二种情况下,你要为名称x
指定一个新对象。 循环迭代的对象在迭代期间不会改变。
只是澄清了Wasi Ahmad和Wisperwind所说的话。 两者都声明“您只是将新对象分配给名称x”。 这可能有点令人困惑,因为它可能被解释为“你正在创建一个新对象( [1]
)并将其存储到名称x
,你会说”好吧,为什么不改变它?!“要查看发生了什么,请打印出对象的ID
x = [1, 2, 3, 4, 5]
y = x # To keep a reference to the original list
print id(x), id(y)
for i, v in enumerate(x):
x = [1]
print id(x), id(y)
print id(x), id(y)
# output (somewhat contrived as I don't have a python environment set up)
# X ID Y ID
10000000000001 10000000000001
10000000000002 10000000000001
10000000000003 10000000000001
10000000000004 10000000000001
10000000000005 10000000000001
10000000000006 10000000000001
10000000000006 10000000000001
你会注意到每次循环时x
的id
都在变化,当你完成循环时, x
将指向循环中的最后一次修改。 当你完成循环时,它会迭代x的原始实例,无论你是否仍然可以引用它。
如您所见, y
指向原始x
。 当您在循环中进行迭代时,即使x
正在改变, y
仍然指向仍在循环的原始x
。
其他人已经指出,你的第二个例子只改变了x
指向的值,而不是你要迭代的列表。 这是普通分配( x = [1]
)和切片分配 ( x[:] = [1]
)之间差异的完美示例。 后者将列表x
点修改为就地 :
x = [1, 2, 3, 4, 5]
for i, s in enumerate(x):
x[:] = [1]
print(i, s, x)
将打印
(0, 1, [1])
x = [1, 2, 3, 4, 5]
列表[1, 2, 3, 4, 5]
用x
标记'
for i, s in enumerate(x):
enumerate()附加另一个标记,因此[1, 2, 3, 4, 5]
现在被标记为x
和y
。 enumerate()将继续使用y
标记,而不是x
标记。
del x[0]
存储在内存中的列表被修改,因此x
和y
现在都引用[2, 3, 4, 5]
或者,当你使用时
x = [1]
在内存中创建了一个新列表[1]
, x
标签现在指向该列表。 y
标记仍指向原始列表。
Python变量的工作原理:
http://foobarnbaz.com/2012/07/08/understanding-python-variables/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.