在 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 对象。这显然与您的原始列表不同。
作为切片传递给 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 对象。这显然与您的原始列表不同。