切片列表的枚举()不能按预期工作

enumerate() for sliced list does not work as expected

列表的 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 <--

为什么会这样?

问题并非来自 enumerate 函数。

实际上,在执行 mylist[:-1] 时,您正在创建一个 new 列表,并对其进行处理。

因此,当您尝试修改列表 (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)

区别在于您是在列表的副本 上进行枚举。在您的第一个示例中,您正在枚举对您正在更改的列表的直接引用,但在第二个示例中,您在列表上使用切片来枚举。切片 returns 一个新的列表对象。

这很重要,因为您正在更改尚未迭代的位置所引用的内容。列表迭代使用不断增加的 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)

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.

无关