切片列表的enumerate()无法按预期工作

时间:2019-04-08 15:03:58

标签: python python-3.x enumerate

列表的

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 <--

为什么会这样?

3 个答案:

答案 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无关。