【问题标题】:How to pass a list by reference?如何通过引用传递列表?
【发布时间】:2018-06-29 23:46:39
【问题描述】:

我正在尝试实现一个函数“添加”,它将列表L1L2 组合成L3

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

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

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

如何通过引用传递L3

【问题讨论】:

  • 不要;只需返回组合列表。 L3 = add([1], [0]).
  • 是的,python支持引用传递语义

标签: python pass-by-reference


【解决方案1】:

如果您想就地进行更改,则需要执行修改列表的操作就地。这意味着任何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)

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • "使用切片分配而不是普通分配。"那么为什么正常分配不起作用呢?
    • 因为L1 + L2 创建了一个分配给L3 的新列表对象,而不是替换L3 已经引用的列表的元素。在许多情况下,这可能无关紧要,但 OP 专门询问他们希望更新现有列表的场景。
    • 所以 L3(对列表 L3 的引用)是按值传递的,而不是按引用传递的,这就是为什么您不能直接更改函数内部的 L3(引用),而必须这样做“切片分配”(因此不必更改 L3)? :P C++ 在这方面有多优雅。
    • 函数与它关系不大。 L3 = ... 从不L3 当前所指的任何内容有任何关系。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      L3[:] = L1 + L2
      

      测试代码:

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

      结果:

      [1, 0]
      

      【讨论】:

      • 我能感同身受的东西!
      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      • 2021-04-15
      • 2014-10-13
      相关资源
      最近更新 更多