Python 更改列表项
我想知道为什么当通过调用函数更改列表值时,以下两种情况存在如此大的差异(将新值分配给 list 与 list[:])。我想这与按值调用/按引用调用有关。
代码
def rotate1(nums, k) -> None:
nums = nums[-k:]+nums[:-k]
print(f"In rotate1: {nums}")
def rotate2(nums, k) -> None:
nums[:] = nums[-k:]+nums[:-k]
print(f"In rotate2: {nums}")
ls1 = [1,2,3,4]
rotate1(ls1, 2)
print(f"Outside rotate1: {ls1}\n")
ls2 = [1,2,3,4]
rotate2(ls2, 2)
print(f"Outside rotate2: {ls2}\n")
输出
In rotate1: [3, 4, 1, 2]
Outside rotate1: [1, 2, 3, 4]
In rotate2: [3, 4, 1, 2]
Outside rotate2: [3, 4, 1, 2]
调用rotate1后ls1值没有改变; 而 ls2 值在调用rotate2后发生变化。
I am wondering why when changing values to a list by calling a function, there is such a difference in the following two scenarios (assign new value to list v.s. to list[:]). I guess it has something to do with call-by-value/call-by-reference.
Code
def rotate1(nums, k) -> None:
nums = nums[-k:]+nums[:-k]
print(f"In rotate1: {nums}")
def rotate2(nums, k) -> None:
nums[:] = nums[-k:]+nums[:-k]
print(f"In rotate2: {nums}")
ls1 = [1,2,3,4]
rotate1(ls1, 2)
print(f"Outside rotate1: {ls1}\n")
ls2 = [1,2,3,4]
rotate2(ls2, 2)
print(f"Outside rotate2: {ls2}\n")
Output
In rotate1: [3, 4, 1, 2]
Outside rotate1: [1, 2, 3, 4]
In rotate2: [3, 4, 1, 2]
Outside rotate2: [3, 4, 1, 2]
ls1 value does not change after calling rotate1;
whereas ls2 value changes after calling rotate2.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
此页面准确解释了相同的问题 Python 是按引用传递还是按值传递?
在这两种旋转方法中,
nums
创建一个新变量来指向对象 [1,2,3,4]。区别在于:nums = nums[-k:]+nums[:-k]
导致nums
指向一个新对象。nums[:] = nums[-k:]+nums[:-k]
导致nums
指向的对象发生变化。因此,在方法之外,只有
rotate2
真正更改了ls2
的对象。The same problem is explained exactly in this page Is Python pass-by-reference or pass-by-value?
In both rotate methods, the
nums
creates a new variable to point to object [1,2,3,4]. The difference is:nums = nums[-k:]+nums[:-k]
causesnums
to point to a new object.nums[:] = nums[-k:]+nums[:-k]
causes the object pointed bynums
changed.So, outside the methods, only the
rotate2
really changes the object ofls2
.在函数
rotate1
中,您分配了一个新变量nums
,它替换了参数中的变量nums
。这不会影响函数外部的列表,因为您正在替换指向内存中分配值的位置的变量,而不是更改内存中的值。本质上,您的新列表[3, 4, 1, 2]
存储在内存中的新地址中。现在,您已将原始列表ls1
和新列表nums
分配在内存中的不同地址中。在函数
rotate2
中,您正在更改存储在内存中的值,而不是更改指针。当您使用 nums[:] 时,变量 nums 保持不变,变化的是变量 nums 指向的内存中的值。这就是为什么您的外部列表也会更新。In your function
rotate1
you are assigning a new variablenums
which replaces the variablenums
that came in the argument. This will not affect the list outside the function because you are replacing the variable that points to where the values are allocated in memory, you are not changing the values in memory. Essentially, your new list[3, 4, 1, 2]
is being stored in a new address in memory. Now you have your original listls1
and the new listnums
allocated in different addresses in memory.In your function
rotate2
you are changing the values that are stored in memory, instead of changing the pointer. When you usenums[:]
the variablenums
remains untouched, what changes are the values in memory that the variablenums
points to. That's why your list outside gets updated too.