我有这段代码只能对保证介于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]
答案 0 :(得分:2)
因为您在行arr
中创建了一个名为arr = []
的新变量,从此时开始操作新列表。同样,您始终使用for
操作在以下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]
答案 1 :(得分:1)
答案 2 :(得分:0)
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的值(指针值,而不是数据被复制)。所以,再次重新分配什么都不做。请注意,id
函数此次输出不同的值。所以在函数返回之后,我们得到x的原始值(指针的原始值,即)