簡體   English   中英

列出Python中的引用混淆

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

通過將[]分配給arr您將丟失對現有數組的引用,並創建一個新數組。

要更改它,您可以使用

inp.sort()

有關排序與排序的更多信息

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM