2017-04-17 91 views
5

我剛開始學習Python和我很困惑這個例子:Python的默認PARAMS混亂

def append_to(element, to=None): 
    if to is None: 
     to = [] 
    to.append(element) 
    return to 

如果to被初始化一次,也不會toNone的第二次它叫什麼名字?我知道上面的代碼可行,但無法圍繞這個「初始化一次」描述。

+0

在這個糟糕的例子中(我稱它不好,因爲如果你傳遞一個'str'這個東西就會崩潰......),無論是'to'是'None'還是一個列表。如果'to'不是'None',則不會創建列表。因此,在這種方式調用下,只給'to'賦值:'append_to('dreamfly')',而在這種情況下:'append_to('dreamfly',users)'where'users'將成爲一個列表,你在函數內部沒有創建任何列表,你只需追加值('users = [...,'dreamfly']')。 – 2017-04-17 19:46:07

+0

這是一個來自http://python-guide-pt-br.readthedocs.io/en/latest/writing/gotchas/ – dreamfly

+0

的例子我給了一些[反饋](https://github.com/kennethreitz/python-guide /問題/ 813);該示例使用非可變對象作爲默認參數,這是一件好事,但遺漏的驗證可能會破壞代碼 – 2017-04-17 21:45:12

回答

1

如果「到」被初始化一次,也不會「到」會不會是「無」的第二次它叫什麼名字?

to將成爲None,如果你不爲它傳遞一個值:append_to(1)只有當toNone將你的代碼重新綁定本地名稱to到新創建的列表你的函數體內部:to = []

功能的默認值只分配一次,這就是您指定爲默認值的任何值,該對象將用於您對該函數進行的每次調用並且不會更改,通常是默認值的相同引用值將用於您對該功能進行的每個呼叫。當你將mutables爲默認這一點很重要:

l = [] 
def defArgs(d=l)   # default arguments, same default list for every call 
    d.append(1) 
    return d 

defArgs() is l   # Object identity test: True 

運行上面的函數多次,你會看到列表中有更多的元素越來越多,因爲你只有一個參數默認的單拷貝通過每個函數調用共享的各項功能。但是請注意這裏:

def localVars(d=None): 
    if d is None: 
     d = []    # Different list for every call when d is None 

d = []執行每次調用localVars時間;當函數完成其作業時,每當引用計數下降到0,而不是參數的默認值時,每個局部變量都被垃圾收集,它們在函數執行後存活,並且通常在執行功能

+0

我想我在閱讀了幾次後明白了你的意思。這裏的關鍵不是變量的範圍,而是用於初始化變量的對象。當他們說「初始化一次」時,它們意味着初始化參數指向一次的對象,並在每次調用函數時將該對象鏈接到參數。所以如果對象是不可變的,它永遠不能改變。如果它是可變的,它將保留最後一個值。現在很清楚。謝謝! – dreamfly

+0

爲了精確,我寧願使用術語*賦值*來代替初始化。是的,你是對的,如果一個對象是不變的,你不能改變它。與mutable不同的是,你可以改變對象'd [0] = 20'的* part *,這裏你真的只是改變了'd'的一部分,即索引0.例如,你不能修改int和tuple的一部分,因爲它們'不變的:a = 20',然後你將a'重新加入到30:'a = 30'現在'a'有一個與30相關的不同的引用,'a'與前面的'a'不一樣。希望這是有道理的:) – direprobs

2
def append_to(element, to=None): 
    to = ... 

to這裏成爲一個局部變量並分配給一個列表,如果你不返回值賦值給另一個變量被釋放。

如果你想to爲後續調用append_to活着,你應該做的:

def append_to(element, to=[]): 
    to.append(element) 
    return to 

演示:

>>> lst = append_to(5) 
>>> append_to(6) 
>>> append_to(7) 
>>> print lst 
[5, 6, 7] 
+0

中「to = []」示例的其他部分,不會「to」也是局部變量,它指向哪個「[]」將被垃圾回收,因爲「to」在函數退出後也會消失? – dreamfly

+0

不,它不是一個局部變量,即使在調用append_to之後它也不會消失,因爲它被綁定到函數中。你一直在調用'append_to',同樣的'to'值增加了新的元素。 – ozgur

+0

那麼是什麼使「to = None」成爲局部變量而「to = []」不是局部變量呢?它依賴於價值的可變性嗎?即使對我來說這仍然有點不合邏輯,但我可以在腦海中記住它。 – dreamfly

0

在Python沒有聲明和初始化階段,當您使用變量。相反,所有賦值都是將實例綁定到變量名稱的定義。

解釋器在實例化函數時將實例綁定到默認值。當默認值是一個可變對象,並且只通過其方法更改其狀態時,該值將在調用之間「共享」。