2012-01-13 16 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)... –

+0

はい、何もしません再帰関数を使用します。 –

+0

aha、ありがとうございます。 –

答えて

4

デフォルトの引数に変更可能な値を使用すると、そのデフォルトのインスタンスが1つだけ取得されます。あなたの関数がそれを変更した場合、それはその関数の次回の呼び出し時に渡されます。

Pythonのドキュメント自体に少なくとも1つの参照があります: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

+0

@julio、ありがとう。今修正されました。ニースのリンクも。私は決してそれを考えなかった:) – FakeRainBrigand