我想知道为什么当通过调用函数将值更改为列表时,以下两种情况会有这样的差异(将新值分配给listv.s.分配给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之后发生变化。
本页中准确解释了同样的问题Python是通过引用传递还是通过值传递?
正如我们所知,在Python中,"对象引用是按值传递的"。
在两种旋转方法中,nums
创建一个新变量以指向对象[1,2,4]。区别在于:
nums = nums[-k:]+nums[:-k]
导致nums
指向一个新对象nums[:] = nums[-k:]+nums[:-k]
导致nums
所指向的对象发生改变
因此,在方法之外,只有rotate2
真正更改ls2
的对象。
在函数rotate1
中,您将分配一个新变量nums
,该变量将替换参数中的变量nums
。这不会影响函数外的列表,因为您正在替换指向内存中值分配位置的变量,而不是更改内存中的值。从本质上讲,您的新列表[3, 4, 1, 2]
存储在内存中的一个新地址中。现在,您已经将原始列表ls1
和新列表nums
分配到内存中的不同地址。
在函数rotate2
中,您正在更改存储在内存中的值,而不是更改指针。当你使用nums[:]
时,变量nums
保持不变,变量nums
指向的内存值发生了什么变化。这就是为什么你的外部列表也会更新的原因。