[英]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.