如何通过引用传递列表?

How to pass a list by reference?

我正在尝试实现一个函数 'add',它将列表 L1L2 合并为 L3:

def add(L1,L2,L3):
    L3 = L1 + L2

L3 = []
add([1],[0],L3)
print L3

上面的代码生成了一个空列表而不是 [1,0] - 这意味着 L3 没有通过引用传递。

如何通过引用传递L3

您可以通过以下方式实现:

L3[:] = L1 + L2

测试代码:

def add(L1, L2, L3):
    L3[:] = L1 + L2

L3 = []
add([1], [0], L3)
print(L3)

结果:

[1, 0]

如果您想就地进行更改,则需要执行修改列表的操作就地。这意味着任何 list 实例方法。在此特定实例中,您可以查看 list.extend.

def add(L1, L2, L3):
    L3.extend(L1 + L2)   # creates a new list object and copies it into L3

由于这会创建一个副本(这可能效率低下),您可以代替在其位置使用两个 extend 调用 -

def add(L1, L2, L3):
    L3.extend(L1)        
    L3.extend(L2)

调用L3.extend 就地修改原始列表。使用您当前的代码,L1 + L2 创建一个新列表,并将 L3 重新分配给该对象(并且未触及 L3 所指的原始对象)。


如果您想将其推广到任意数量的列表,我建议您查看使用可变参数:

from itertools import chain

def add(L3, *L):
    L3.extend(chain.from_iterable(L))

这是它如何工作的一个例子:

>>> L3 = []
>>> add(L3, [1], [2], [3])
>>> L3
[1, 2, 3]

作为一种良好做法,您应该

  • 定义一个不修改原始结构的函数,但returns一个你可以从调用者分配的新值,或者
  • 定义一个修改结构的函数,returns什么都不做。

另一个用户注意事项:L3[:] = ... 将其所有以前的内容 L3 替换为 L1 + L2 中的项目。另一方面,L3.extend(...) 不会破坏之前在 L3 中的内容,而是通过传递的内容 扩展 。我建议评估您的用例并根据情况使用更合适的方法。

但是,为了迎合这种情况,您可以使用 __setitem__:

就地赋值来构建已接受答案的方法
def add(L3, *L):
    L3[:] = chain.from_iterable(L)

其工作方式相同,并且对于许多列表应该非常有效。

列表已经通过引用传递,因为 all Python 名称是引用,列表对象是可变的。使用切片分配而不是正常分配。

def add(L1, L2, L3):
    L3[:] = L1 + L2

但是,这不是编写函数的好方法。您应该 return 组合列表。

def add(L1, L2):
    return L1 + L2

L3 = add(L1, L2)

您不能在 Python 中通过引用显式传递变量,但您可以更新现有对象的属性。

因此,您可以做的是更新 L3 上的值,所有这些都适合您的情况,因此您可以这样做:

def add(L1 ,L2, L3):
    L3[:] = L1 + L2

L3 = []

add([1], [0], L3)

print L3