enumerate()工作正常。
def swap(nums, i, j):
temp = nums[i]
nums[i] = nums[j]
nums[j] = temp
mylist = [0,1,22,33,4]
for pos, num in enumerate(mylist):
print(pos,num)
if pos == 0:
swap(mylist,2,3)
在此示例中,num
显示了预期的交换值。
0 0
1 1
2 33 <--
3 22 <--
4 4
但是,如果我将mylist
更改为mylist[:-1]
,例如:
def swap(nums, i, j):
temp = nums[i]
nums[i] = nums[j]
nums[j] = temp
mylist = [0,1,22,33,4]
for pos, num in enumerate(mylist[:-1]):
print(pos,num)
if pos == 0:
swap(mylist,2,3)
num
不显示交换的值。
0 0
1 1
2 22 <--
3 33 <--
为什么会这样?
答案 0 :(得分:2)
问题并非来自enumerate
函数。
实际上,在进行mylist[:-1]
时,您是在创建新列表并进行处理。
因此,当您尝试修改列表(swap(mylist,2,3)
)时,您将修改原始列表,而不是新列表(由mylist[:-1]
创建)。
您可以通过以下方法解决问题:
new_list = mylist[:-1]
for pos, num in enumerate(new_list):
print(pos,num)
if pos == 0:
swap(new_list,2,3)
答案 1 :(得分:1)
区别在于您要枚举列表的副本。在第一个示例中,您正在枚举要更改的列表的直接引用,但是在第二个示例中,您使用了对列表的切片来枚举。切片将返回一个新的列表对象。
这很重要,因为您正在更改尚未引用的位置。列表迭代使用不断增加的 index 来产生值,在迭代时更改列表可能意味着下一个索引引用了另一个值。
通过enumerate()
函数完成迭代并不重要。如果没有enumerate()
,您会遇到同样的问题:
for num in mylist:
print(num)
if num == 0:
swap(mylist, 2, 3)
将打印
0
1
33
22
4
切片会给你一个副本,所以:
for num in mylist[:-1]:
print(num)
if num == 0:
swap(mylist, 2, 3)
输出
0
1
22
33
如果目标是跳过最后一个元素,则可以通过枚举位置尽早退出循环,而不必通过切片来创建副本:
for pos, num in enumerate(mylist):
if pos == len(mylist) - 1:
break
print(pos, num)
if pos == 0:
swap(mylist, 2, 3)
或者您可以使用itertools.islice()
function
from itertools import islice
for pos, num in enumerate(islice(mylist, len(mylist) - 1)):
print(pos, num)
if pos == 0:
swap(mylist, 2, 3)
或者您可以简单地先创建副本 ,然后更改该副本的索引:
sliced = mylist[:-1]
for pos, num in enumerate(sliced):
print(pos, num)
if pos == 0:
swap(sliced, 2, 3)
答案 2 :(得分:1)
mylist[:-1]
正在创建一个新的列表对象,但是您使用mylist
执行交换。
您怎么知道它是另一个对象?
您可以使用id()
测试此行为:
>>> mylist = [0,1,22,33,4,5]
>>> id(mylist)
3954492760
>>> lst = mylist
>>> id(lst)
3954492760
>>> sliced = mylist[:-1]
>>> id(sliced)
3954492920
如果您观察到,sliced
的ID是不同的。
for pos, num in enumerate(mylist[:-1]):
print(pos,num)
if pos == 0:
swap(mylist,2,3)
# ^^^ - you used a different list object from what you were iterating over.
您可以做的最简单修复是预先切片:
sliced = mylist[:-1]
for pos, num in enumerate(sliced):
print(pos,num)
if pos == 0:
swap(sliced,2,3)
因此,正如其他人所提到的,这与enumerate
无关。