2017-05-20 25 views
2

我有這段代碼只是對保證介於0和R-1(含)之間的數字列表進行排序。以下代碼正確排序,但我不明白爲什麼傳入的輸入保持不變。在Python中通過引用混淆列表傳遞

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] 
+1

)在python *中不支持通過引用語義*。 –

+1

閱讀:https://nedbatchelder.com/text/names.html –

回答

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

通過分配[]arr你失去了參照現有的陣列,並創建一個新的。

要改變它,你可以使用

inp.sort() 

More info on sort vs sorted

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傳入之前(指針值,而不是數據被複制)複製了x的值。所以,再分配也沒有作用。請注意,id函數此次輸出不同的值。所以在函數返回後,我們得到x的原始值(指針的原始值,即