如何通过引用将切片传递给函数

How to pass slice into a function by reference

如果我有

a = [1, 2, 3]

def foo (arr):
    for i in len (arr): arr [i] += 1

def bar (arr):
    foo (arr[:2])

bar (a)
print (a)

我希望输出为

>>> [2, 3, 3 ]

我该怎么做?

动机:我想要一个优先级队列,我可以在其中冻结最后 N 个元素,即仅将 queue[:N] 传递给 heapq.heappush()。但是,每次我将切片传递给它或传递给任何一般函数时,它都会向函数发送切片的副本而不是实际列表,因此我的列表最终保持不变。

使用列表理解并使用完整切片分配更新初始列表 [:]:

def foo(arr):
   arr[:] = [x+1 for x in arr]

试用:

>>> a = [1, 2, 3]
>>> def foo(arr):
...    arr[:] = [x+1 for x in arr]
...
>>> foo(a)
>>> a
[2, 3, 4]

切片列表将创建一个包含切片内容的新列表,因此arr[:2]失去对原始a的引用。

除此之外,像您一样进行迭代根本不会更改列表,它只会更改 item 而忽略值。

如果您想更改列表的特定部分,您必须随身携带对原始列表的引用。例如,保留 arr,用 enumerate(arr[:2]) 遍历它的一部分,然后更改 arr:

a = [1, 2, 3]

def foo(arr):
    for i, item in enumerate(arr[:2]): 
        arr[i] = item + 1

def bar(arr):
    foo(arr)

bar(a)
print(a)

打印现在生成 [2, 3, 3],移除 enumerate 中的切片生成 [2, 3, 4]。当然,这里的bar没有任何作用,你可以放弃它,保留foo并立即调用foo(a)

老实说,我不会去切片,而是传递索引;

a = [1, 2, 3]
def foo(array, start, stop, jmp= 1):
    for idx in range(start, stop + 1, jmp):
        array[idx] += 1

def bar(array):
    foo(array, 1, 2)
bar(a)
print(a)
[1, 3, 4]

如果 a 是 numpy 数组,这将起作用。默认情况下,numpy 个切片引用与原始数组相同的内存块。

import numpy as np
a = np.array([1, 2, 3])

def foo(arr):
    for i in range(len(arr)): arr[i] += 1
    # or just arr += 1

def bar(arr):
    foo(arr[:2])

bar(a)
print(a)
# [2, 3, 3 ]