切片列表的枚举()不能按预期工作
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
.
无关
列表的 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
.