2012-10-09 77 views
-1

下面是一些代碼:我怎樣才能在Python實現這一

li=[1,2,3] 
def change(l): 
    l[2]=10 
change(li) 
print li 
[1, 2, 10] 

但我想這一點:

li=[1,2,3] 
def change(l): 
    l=[1,2,10] 
change(li) 
print li 
[1,2,3] 

出於某種原因,我不得不改變方法整個列表,我如何能實現這個?有什麼不對或我的錯誤?

+1

[Python和引用傳遞的可能重複。限制?](http://stackoverflow.com/questions/12797749/python-and-reference-passing-limitation) – delnan

+0

我也只能猜測你的問題是什麼,但如果我正確理解你,你想知道爲什麼你在change()裏面的改變在外面是可見的。閱讀此:http://stackoverflow.com/a/986145/112308 – rodion

回答

2

當你想改變一個方法裏面的整個列表,你可能會想創建一個副本和回報它:

def change(li): 
    new_list = li[:] #copy 
    new_list[2] = 10 
    return new_list 

li = [1,2,3] 
new_lst = change(li) #new_lst = [1,2,10] 

如果你不想返回名單,但希望在的地方進行修改,你可以用切片賦值(*警告:這是不常見的做法):

def change(li): 
    li[:] = [1,2,10] 

li = [4,5,6] 
change(li) 
print(li) #[1, 2, 10] 
0

使用別名

文檔:List Aliasing — How to Think like a Computer Scientist (2nd editon)

您可以利用Python的名單走樣(這是common gotcha初學者)。

當通過lichange功能,l別名li,即它們都指向同一個對象在存儲器中並改變一個改變另一個。但是當你做l = [1, 2, 10]l指向另一個列表,你失去了別名魔術。要解決這一點,你可以用切片操作來代替完整名單像這樣:

li = [1, 2, 3] 
def change(l): 
    l[:] = [1, 2, 10] # doesn't make a new list 
change(li)    # preserves aliasing 
print li    # returns [1, 2, 10] 


使用全局

文檔:The global statement — Python Docs

的f中的變化爲l不適用於li列表外。您可以使用一個全球性的影響li列表你想改變:

li = [1, 2, 3] 
def change(): 
    global li 
    li = [1, 2, 10] # use this 
    li[2] = 10  # or this, up to you 
change() 
print li    # returns [1, 2, 10] 
1

像這樣:

li = [1, 2, 3] 

def change(l): 
    l[:] = [1, 2, 10] 

change(li) 
print li # [1, 2, 10] 

你的方法是行不通的原因是,在Python中,變量只是名字那個引用對象。當您編寫l = [1, 2, 10]時,您將重新綁定名稱l以引用您剛剛創建的新列表,舊列表未更改,仍由全局變量li引用。

上述代碼改爲使用slice assignment修改l指向的對象。

由於mgilson在他的回答中指出,您應該非常清楚該函數實際上是否就地修改了傳遞的參數。如果沒有,一個毫無戒心的程序員可能會通過一個他打算以後使用的列表,只是發現其中的所有內容都已經丟失。給你的函數一個表示修改的名字(就像你已經完成的一樣)並且不返回任何東西都是這些函數的通用指示符,例如random.shuffle

爲了達到一個字典一樣的效果,documentation告訴我們,這是不行的:

def change_dict(d): 
    d.clear() # Empty dict 
    d.update({"a": 3, "b": 9}) 
+0

謝謝,如果我想改變一個字典相同的這個,我怎麼能得到這個? – Wahaha

+0

@Wahaha查看最新的答案。 –

+0

@lazyr所以字典和其他對象也會變成別名?關於自定義對象的事情? –

0

當你做到以下幾點:

def change(l): 
    l=[1,2,10] 

你實際上改變其名單l點至。您需要將傳入的列表實例更改爲change。你可以從append到它,你可以從它pop等,你的變化將被傳遞到你通過的列表。如果你改變你的change功能,我的例子將工作。

def change(l): 
    l[:] = [1,2,10] 
0

在此代碼中,l是作爲普通對象工作的,因此您可以通過提供對象內存位置的id()來檢查。 所以這就是爲什麼你,如果你想你所需的輸出比你使用提供心虛對象功能deepcopy的拿到了最後輸出[1,2,10]

l = [1, 2, 3] 
print id(l) 
def change(l): 
    l[:] = [1, 2, 10] 
    print id(l) 
change(l) 
print l 
print id(l) 

from copy import deepcopy 
l = [1, 2, 3] 
print id(l) 
def change(l): 
    l[:] = [1, 2, 10] 
    print id(l) 
change(deepcopy(l)) 
print l 
print id(l)