Python:通过引用传递和切片分配

Die*_*tas 4 python reference function list python-2.7

在Python中,列表通过引用函数传递,对吧?

如果是这样,那里发生了什么?

>>> def f(a):
...     print(a)
...     a = a[:2]
...     print(a)
...
>>> b = [1,2,3]
>>> f(b)
[1, 2, 3]
[1, 2]
>>> print(b)
[1, 2, 3]
>>>
Run Code Online (Sandbox Code Playgroud)

AGN*_*zer 6

在声明中:

a = a[:2]
Run Code Online (Sandbox Code Playgroud)

您正在创建一个新的本地(to f())变量,您使用与输入参数相同的名称调用该变量a.

也就是说,你所做的相当于:

def f(a):
    print(a)
    b = a[:2]
    print(b)
Run Code Online (Sandbox Code Playgroud)

相反,您应该a 在适当的位置进行更改,例如:

def f(a):
    print(a)
    a[:] = a[:2]
    print(a)
Run Code Online (Sandbox Code Playgroud)


Art*_*yer 5

当你这样做时:

a = a[:2]
Run Code Online (Sandbox Code Playgroud)

它重新分配a给一个新值(列表的前两项).

所有Python参数都通过引用传递.您需要更改它所a引用的对象,而不是引用新对象.

a[2:] = []
# or
del a[2:]
# or
a[:] = a[:2]
Run Code Online (Sandbox Code Playgroud)

第一个和最后一个分配给列表的切片,就地更改列表(影响其值),中间一个也通过删除其余元素来更改列表的值.


Ash*_*ary 4

事实上,对象是通过引用传递的,但a = a[:2]基本上创建了一个指向列表切片的新局部变量。

要就地修改列表对象,您可以将其分配给其切片(切片分配)。

考虑a和b这里相当于你的 globalb和 local a,这里分配a给新对象不会影响b:

>>> a = b = [1, 2, 3]    
>>> a = a[:2]  # The identifier `a` now points to a new object, nothing changes for `b`.
>>> a, b
([1, 2], [1, 2, 3])
>>> id(a), id(b)
(4370921480, 4369473992)  # `a` now points to a different object
Run Code Online (Sandbox Code Playgroud)

按预期分割分配工作:

>>> a = b = [1, 2, 3]    
>>> a[:] = a[:2]  # Updates the object in-place, hence affects all references.
>>> a, b
([1, 2], [1, 2])
>>> id(a), id(b)
(4370940488, 4370940488)  # Both still point to the same object
Run Code Online (Sandbox Code Playgroud)

相关:对整个列表进行切片的切片赋值和直接赋值有什么区别?