在 python 中作为切片传递给 enumerate() 时是否形成了数组的新副本?

Is a new copy of array formed when passed as a slice to enumerate() in python?

作为切片传递给 enumerate() 时是否形成了数组的新副本?这是我在 运行 以下实验后的猜测。在我看来是这样,但我不确定如何用代码证明我的想法?

下面是一段代码和 2 个结果。 A选项和B选项对应的结果也如下

def selection_sort(arr):
    # for idx, item in enumerate(arr[:-1]):        # option A
    for idx, item in enumerate(arr):        # option B
        curr_min = item
        swap_ptr = idx
        
        print('========================================')
        print('curr_min: {}'.format(curr_min))
        print('arr before: {}'.format(arr))
        
        for j in range(idx+1, len(arr)):
            print('for item {}'.format(arr[j]))
            if arr[j] < curr_min:
                print('{} < {}'.format(arr[j], curr_min))
                curr_min = arr[j]
                swap_ptr = j
                print('swap_ptr now at {} pointing to {}'.format(swap_ptr, curr_min))
        
        (arr[idx], arr[swap_ptr]) = (arr[swap_ptr], arr[idx])
        print('arr after: {}'.format(arr))
        
    return arr
    
print(selection_sort([5,9,1,3,0,20,77,46]))
        

运行 对选项 A 的结果(即注释掉选项 B):

========================================
curr_min: 5
arr before: [5, 9, 1, 3, 0, 20, 77, 46]
for item 9
for item 1
1 < 5
swap_ptr now at 2 pointing to 1
for item 3
for item 0
0 < 1
swap_ptr now at 4 pointing to 0
for item 20
for item 77
for item 46
arr after: [0, 9, 1, 3, 5, 20, 77, 46]
========================================
curr_min: 9
arr before: [0, 9, 1, 3, 5, 20, 77, 46]
for item 1
1 < 9
swap_ptr now at 2 pointing to 1
for item 3
for item 5
for item 20
for item 77
for item 46
arr after: [0, 1, 9, 3, 5, 20, 77, 46]
========================================
curr_min: 1
arr before: [0, 1, 9, 3, 5, 20, 77, 46]
for item 3
for item 5
for item 20
for item 77
for item 46
arr after: [0, 1, 9, 3, 5, 20, 77, 46]
========================================
curr_min: 3
arr before: [0, 1, 9, 3, 5, 20, 77, 46]
for item 5
for item 20
for item 77
for item 46
arr after: [0, 1, 9, 3, 5, 20, 77, 46]
========================================
curr_min: 0
arr before: [0, 1, 9, 3, 5, 20, 77, 46]
for item 20
for item 77
for item 46
arr after: [0, 1, 9, 3, 5, 20, 77, 46]
========================================
curr_min: 20
arr before: [0, 1, 9, 3, 5, 20, 77, 46]
for item 77
for item 46
arr after: [0, 1, 9, 3, 5, 20, 77, 46]
========================================
curr_min: 77
arr before: [0, 1, 9, 3, 5, 20, 77, 46]
for item 46
46 < 77
swap_ptr now at 7 pointing to 46
arr after: [0, 1, 9, 3, 5, 20, 46, 77]
[0, 1, 9, 3, 5, 20, 46, 77]

选项 B 的 运行 结果(即注释掉选项 A):

========================================
curr_min: 5
arr before: [5, 9, 1, 3, 0, 20, 77, 46]
for item 9
for item 1
1 < 5
swap_ptr now at 2 pointing to 1
for item 3
for item 0
0 < 1
swap_ptr now at 4 pointing to 0
for item 20
for item 77
for item 46
arr after: [0, 9, 1, 3, 5, 20, 77, 46]
========================================
curr_min: 9
arr before: [0, 9, 1, 3, 5, 20, 77, 46]
for item 1
1 < 9
swap_ptr now at 2 pointing to 1
for item 3
for item 5
for item 20
for item 77
for item 46
arr after: [0, 1, 9, 3, 5, 20, 77, 46]
========================================
curr_min: 9
arr before: [0, 1, 9, 3, 5, 20, 77, 46]
for item 3
3 < 9
swap_ptr now at 3 pointing to 3
for item 5
for item 20
for item 77
for item 46
arr after: [0, 1, 3, 9, 5, 20, 77, 46]
========================================
curr_min: 9
arr before: [0, 1, 3, 9, 5, 20, 77, 46]
for item 5
5 < 9
swap_ptr now at 4 pointing to 5
for item 20
for item 77
for item 46
arr after: [0, 1, 3, 5, 9, 20, 77, 46]
========================================
curr_min: 9
arr before: [0, 1, 3, 5, 9, 20, 77, 46]
for item 20
for item 77
for item 46
arr after: [0, 1, 3, 5, 9, 20, 77, 46]
========================================
curr_min: 20
arr before: [0, 1, 3, 5, 9, 20, 77, 46]
for item 77
for item 46
arr after: [0, 1, 3, 5, 9, 20, 77, 46]
========================================
curr_min: 77
arr before: [0, 1, 3, 5, 9, 20, 77, 46]
for item 46
46 < 77
swap_ptr now at 7 pointing to 46
arr after: [0, 1, 3, 5, 9, 20, 46, 77]
========================================
curr_min: 77
arr before: [0, 1, 3, 5, 9, 20, 46, 77]
arr after: [0, 1, 3, 5, 9, 20, 46, 77]
[0, 1, 3, 5, 9, 20, 46, 77]

请告诉我如何证明我对这个奇怪现象的看法。似乎当数组以切片方式传递给 enumerate() 时,它只会迭代函数参数列表中的 'old' 数组。但是当在没有任何切片的情况下传递时, enumerate() 迭代在循环内修改的新数组。我不确定我是否可以使用代码和文档而不是 运行 这个实验来证明这一点?为什么这个设计如此奇怪? TIA.

我可以确认是这样的。来看看我的作品吧

我首先创建一个基本列表:

foo = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

然后,当我们迭代枚举时,我将编辑其中一个值:

>>> once = True
>>> for idx, val in enumerate(foo):
...  if once:
...   once = False
...   foo[2] = 666
...  print(idx, val)
... 
0 0
1 1
2 666
3 3
4 4
5 5
6 6
7 7
8 8
9 9

我们注意到枚举在到达其索引时显示编辑后的值。

现在我们在传递切片而不是原始切片时执行相同的操作:

>>> foo = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> once = True
>>> for idx, val in enumerate(foo[:]):
...  if once:
...   once = False
...   foo[2] = 42
...  print(idx, val)
... 
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
>>> foo
[0, 1, 42, 3, 4, 5, 6, 7, 8, 9]

我们看到虽然 foo 已经被编辑,枚举并不知道这个变化,因为它必须使用原始的未修改副本。

我调查了为什么会这样。当 using the bracket notation we are actually calling the slice class 在引擎盖下时。

这表明它 returns 一个 Slice 对象。这显然与您的原始列表不同。

有兴趣的还可以看the object creation in the source code