如何通过引用传递列表?

时间:2018-01-21 02:17:52

标签: python pass-by-reference

我正在尝试实施一项功能'添加'它将列表L1L2合并为L3

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

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

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

如何通过引用传递L3

4 个答案:

答案 0 :(得分:6)

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

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

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

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

L3 = add(L1, L2)

答案 1 :(得分:5)

您可以通过以下方式实现此目的:

L3[:] = L1 + L2

测试代码:

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

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

结果:

[1, 0]

答案 2 :(得分:4)

如果您希望在地方进行更改,则需要执行修改列表 inplace 的操作。这将意味着任何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]

作为一种良好的做法,你应该

  • 定义一个不修改原始结构的函数,但返回一个可以从调用者分配的新值,或者
  • 定义一个修改结构的函数,并且不返回任何内容。

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

但是,为了迎合这种情况,您可以使用__setitem__的就地分配建立在接受的答案方法上:

def add(L3, *L):
    L3[:] = chain.from_iterable(L)

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

答案 3 :(得分:1)

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

因此,你可以做的是更新L3的值,在你的情况下更新所有值,所以你可以这样做:

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

L3 = []

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

print L3