简体   繁体   English

如何通过引用传递列表?

[英]How to pass a list by reference?

I'm trying to implement a function 'add' that combines the list L1 with L2 into L3 : 我正在尝试实现一个函数'add',它将列表L1L2L3

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

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

The code above produces an empty list as a result instead of [1,0] - This means that L3 wasn't passed by reference. 上面的代码产生一个空列表而不是[1,0] - 这意味着L3没有通过引用传递。

How to pass L3 by reference? 如何通过引用传递L3

Lists are already passed by reference, in that all Python names are references, and list objects are mutable. 列表已经通过引用传递,因为所有 Python名称都是引用,列表对象是可变的。 Use slice assignment instead of normal assignment. 使用切片分配而不是正常分配。

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

However, this isn't a good way to write a function. 但是,这不是编写函数的好方法。 You should simply return the combined list. 您应该只返回组合列表。

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

L3 = add(L1, L2)

You can achieve this with: 你可以用:

L3[:] = L1 + L2

Test Code: 测试代码:

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

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

Results: 结果:

[1, 0]

If you want changes to be made inplace, you'd need to perform operations that modify the list inplace . 如果你想被就地进行更改,你需要执行修改列表就地操作。 This would mean any of the list instance methods. 这将意味着任何list实例方法。 In this particular instance, you could look at list.extend . 在这个特定的实例中,您可以查看list.extend

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

Since this creates a an copy (which may be inefficient), you can instead use two extend calls in its place - 因为这将创建一个拷贝的(可能是低效的),可以改为使用两个extend在它的地方电话-

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

Calling L3.extend modifies the original list in place. 调用L3.extend修改原始列表。 With your current code, L1 + L2 creates a new list, and re-assigns L3 to that object (and the original object that L3 was referring to was not touched). 使用当前代码, L1 + L2创建一个新列表,并将L3重新分配给该对象(并且未触及L3所指的原始对象)。


If you'd like to generalise this to any number of lists, I'd recommend taking a look at using variable arguments: 如果你想将它推广到任意数量的列表,我建议你看一下使用变量参数:

from itertools import chain

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

Here's an example of how it works: 这是一个如何工作的例子:

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

As a matter of good practice, you should either 作为一个良好的实践,你应该

  • define a function that does not modify the original structure, but returns a new value you can assign from the caller, OR 定义一个不修改原始结构的函数,但返回一个可以从调用者分配的新值OR
  • define a function that modifies structures in place, and returns nothing. 定义一个修改结构的函数,不返回任何内容。

Another user note: L3[:] = ... will replace L3 of all its previous contents with the items from L1 + L2 . 另一个用户注意事项: L3[:] = ... L1 + L2的项目替换其所有先前内容的L3 On the other hand, L3.extend(...) will not destroy what was previously in L3 , but is instead extended by what it is passed. 另一方面, L3.extend(...)不会破坏先前在L3 ,而是通过它传递的内容进行扩展 I'd recommend evaluating your use case and using the more appropriate method to the situation. 我建议您评估您的用例并使用更合适的方法来处理这种情况。

However, to cater to that case, you can build on the accepted answer's method using inplace assignment with __setitem__ : 但是,为了迎合这种情况,您可以使用__setitem__使用就地分配来构建接受的答案方法:

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

Which works the same way, and should be very efficient for many lists. 其工作方式相同,对于许多列表应该非常有效。

You can't explicitly pass a variable by reference in Python, but you can update properties on existing objects. 您不能通过Python中的引用显式传递变量,但可以更新现有对象的属性。

Therefore, what you can do is update values on L3 , all of them in your case, so you could do it like this: 因此,您可以做的是更新L3值,所有这些都在您的情况下,所以您可以这样做:

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

L3 = []

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

print L3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM