2012-01-13 80 views
3

可能重複:
「Least Astonishment」 in Python: The Mutable Default ArgumentPython函數和空字符串

編輯:這有什麼好做recusion並且僅僅是可變的默認參數功能:"Least Astonishment" and the Mutable Default Argument

許多感謝

我使用python 2.7.2上WIN7 64位的機器,並有其作用的LXML元件上的遞歸函數,該函數是這樣的:

def recursive_search(start, stack = []): 
    for element in start.getchildren(): 
     if condition1(element): 
      stack = recursive_search(element, stack) 
     elif condition2(element) 
      stack.append(element) 
     else: 
      pass 
    return stack 

當我調用該函數首次用:

output = recursive_search(starting_element) 

它工作正常,我得到了我希望,但如果我有完全相同的命令再次調用它,我得到兩次我所期望的,因爲如果我叫:

output += recursive_search(starting_element) 

或如果堆棧是一個全局變量。如果我說它是我第三次拿到3倍的輸出等等,等等

如果我稱之爲:

output = recursive_search(starting_element, []) 

然後,我可以把這個很多次,因爲我喜歡,我沒有得到反常的行爲。

同樣,如果我修改功能,使得它寫着:

def recursive_search(start, stack = []): 
    if stack == []: 
     stack = [] 
    for element in start.getchildren(): 
     if condition1(element): 
      stack = recursive_search(element, stack) 
     elif condition2(element) 
      stack.append(element) 
     else: 
      pass 
    return stack 

然後我可以叫:

output = recursive_search(starting_point) 

很多次,因爲我喜歡,再沒有得到異常行爲。

我的問題是:到底是怎麼回事 - 這是一個錯誤,還是有一個規則我不知道傳球空字符串時,進入遞歸函數在Python?

+5

那麼,[可變默認參數](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument)再次... – 2012-01-13 16:04:23

+0

是的,沒什麼可做的具有遞歸功能。 – 2012-01-13 16:06:13

+0

哈哈,謝謝。 – 2012-01-13 16:06:48

回答

4

當您使用默認參數一個可變值,你只能得到默認的一個實例。如果你的函數修改它,那麼下一次調用該函數時會傳遞這個函數。

有至少一個參考這個Python文檔本身:http://docs.python.org/release/2.5.2/ref/function.html。請參閱「在執行功能定義時評估默認參數值」一節。

4

@馬克已經解釋過了,這裏有一個解決方案。

def recursive_search(start, stack = None): 
    if stack is None: 
     stack = [] 
    for element in start.getchildren(): 
     if condition1(element): 
      stack = recursive_search(element, stack) 
     elif condition2(element) 
      stack.append(element) 
     else: 
      pass 
    return stack 

不同之處在於使用默認參數時[]被評估一次。當它位於函數的主體中時,每次調用都會創建一個新列表。


一些變化是,

stack = stack or [] 

# or 
if not stack: 
    stack = [] 

不同的是空列表總是會以新的清單取代。這意味着如果你傳遞一個包含一個空列表的變量,當你使用這些變體時,函數將會變爲而不是

當您將其與無比較時,僅在stack包含無時纔會被替換。我想這種方法更安全。

+0

它不建議使用'if stack == None',使用'if stack is None'而不是([更多關於它](http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs -none.html)) – juliomalegria 2012-01-13 17:09:03

+0

@ julio,謝謝。現在已經修復了。尼斯鏈接也。我從來沒想過這點 :) – FakeRainBrigand 2012-01-13 17:13:40