[英]List pass by reference confusion in Python
我有一段代码,只对保证在0到R-1(含)之间的数字列表进行排序。 以下代码正确地进行了排序,但是我不明白为什么传入的输入保持不变。
def bucket(arr, R):
assert type(arr) is list
for i in arr:
assert i >=0 and i < R
b = [0] * R
for i in arr:
b[i]+=1
arr = []
for ind, v in enumerate(b):
arr = arr + [ind] * v
print(arr)
为什么在此示例中inp
在调用函数后没有发生变化:
>>> inp
[3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
>>> bucket(inp, 8)
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
>>> inp # unchanged, why?
[3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
因为您在arr = []
行中创建了一个名为arr
的新变量,并且从这一点开始,您将对新列表进行操作。 同样,你永远是以下中创建新的列表for
-loop与arr = arr + [ind] * v
操作。
您可以将其更改为:
def bucket(arr, R):
assert type(arr) is list
for i in arr:
assert i >= 0 and i < R
b = [0] * R
for i in arr:
b[i] += 1
arr[:] = [] # remove all items from the list (in-place)
for ind, v in enumerate(b):
arr.extend([ind] * v) # extend the list in-place, you could also use "arr += [ind] * v"
print(arr)
例:
>>> inp = [3, 1, 4, 5, 4, 5, 5, 5, 1, 5]
>>> bucket(inp, 8)
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
>>> inp
[1, 1, 3, 4, 4, 5, 5, 5, 5, 5]
Python通过赋值传递,其语义与Java的值传递极为相似。
之所以会出现混乱,是因为您正在按值传递指针 。 这意味着您不能在函数内部修改指针,但是没有人可以阻止您修改指针指向的内容 (即数据)。因此,例如:
x = 3
def change_x(x):
x = 5
return x
change_x(x)
print x
# Outputs 3
函数外部的x值(在本例中为3)在x进入函数之前已被复制,因此赋值不执行任何操作。 这通常是我们听到按值传递时所期望的结果。
x = [1,2,3]
print(id(x))
# Outputs some "address"
def change_x(x):
x.clear()
x.extend([4,5,6])
print(id(x))
# Outputs the SAME address as above
return x
change_x(x)
print(x)
# Outputs [4,5,6]
有没有搞错。 我以为我们只是说我们不能改变x。 问题是我们没有改变x! 我们只是更改了x指向的数据(此处存在细微但重要的区别)。 x仍然是相同的指针。 请注意,由id
输出的地址是相同的。
x = [1,2,3]
print(id(x))
# Outputs some "address"
def change_x(x):
x = [4,5,6]
print(id(x))
# Outputs some DIFFERENT "address". The pointer to x was changed (inside this function).
return x
change_x(x)
print(x)
# Outputs [1,2,3]
它在传递x之前复制了x的值(复制了指针值,而不是数据)。 因此,再分配也无济于事。 注意,这次id
函数输出不同的值。 因此,在函数返回之后,我们得到x的原始值(即指针的原始值)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.