2012-01-21 24 views
2

「a = a」と「b = b」が問題/予期しない動作につながるのではないかと疑問に思っていましたか?コードはこの例でうまく動作します。Pythonのデフォルトの引数と引数名

def add_func(a=2,b=3): 
    return a+b 

a=4 
b=5 
answer = add_func(a=a, b=b) 

私が間違って証明するのが大好きですが、私は、の知っていることを感謝し

答えて

5

ありません。

公式言語リファレンスはthe lexical structure of a function callと定義されています。重要なことは、「keyword_item」をidentifier "=" expressionと定義していることです。また、ここでは、呼び出しの引数がどのように解釈されるかについて述べているものです:

キーワード引数が存在する場合は、次のように、彼らは最初、 位置引数に変換されます。まず、空きスロットのリストは、仮パラメータ用に作成された です。 N個の位置が の場合、最初のNスロットに配置されます。次に、 キーワード引数ごとに、識別子が 対応スロットを特定するために使用されます(識別子が最初の形式 と同じ場合、最初のスロットが使用されます)。スロットが に既に埋め込まれている場合は、TypeError例外が発生します。それ以外の場合は、引数の値 がスロットに挿入されます( の式がNoneの場合でも、スロットはいっぱいになります)。すべての引数が に処理されると、未充填のスロットは、関数定義の対応するデフォルト値の で埋められます。

これにはいくつかのシナリオがあります。

  1. 2つのスロット:そこに2つの仮引数(ab)があり、そしてあなたがadd_func(a=a, b=b)のようなキーワードパラメータを使用して、関数呼び出しを指定した場合、ここでは何が起こるかだ単純なケースで

    、あなたが言及したように、パラメータを保持するために作成されます。

  2. 呼び出しに位置指定引数を指定しなかったため(キーワード引数のみ)、最初にスロットがいっぱいになりません。
  3. それぞれのキーワード引数が個別に分析され、引数の識別子a=部分の「a」)が、関数のすべての仮パラメータ名と比較されます(パラメータの与えられた名前関数が定義されたとき、この場合、ab)。
  4. 一致が発生すると、対応するスロットにはキーワード引数の(この場合は4!)が使用されます。
  5. これは、すべてのキーワード引数が解析されるまで繰り返されます。すべてのスロットが満たされていない場合、Pythonは残りのスロットが存在する場合、デフォルト値を割り当てようとします。そうでない場合は、エラーが発生します。

したがって、Pythonはキーワード引数の "識別子"を完全に異なる方法で扱います。しかし、これはキーワード引数にのみ当てはまります。明らかに、add_func(b, a)のようなものを試した場合、パラメータ自体はbaと呼ばれますが、ではなく、は関数の仮パラメータにマップされます。あなたのパラメータは後方になります。ただし、add_func(b=b, a=a)は問題ありません。キーワードの引数である限り、位置は重要ではありません。

+0

詳細な回答ありがとうございます。私は 'a = a'を使用する習慣に慣れてきました。さまざまなものに同じ記述的な名前をつけておくことができます。すべてのコードを元に戻して変更する必要はありません。 –

0

グローバルオブジェクトが変更可能か不変かどうかによって異なります。あなたの整数のような不変のオブジェクトは、変更されたときにコピーされるので、安全です。リストのような変更可能なオブジェクトは、インプレースで変更され、この方法で使用するのは安全ではありません。それらに何らかの変更があっても、呼び出し間で継続され、予期しない動作を引き起こす可能性があります。

この:Pythonプログラムの既知の悪い習慣がある

def f(a=[]): 
    pass 

a=[] 
def f(a=a): 
    pass 

は同じです。

+2

ここで重要なのは、**関数呼び出し**で 'a = a'を使用することには実際には関係しませんが、これは[関数が定義されているときにデフォルトパラメータが評価される_once_](http ://docs.python.org/reference/compound_stmts.html#function)。 – voithos

+0

これを指摘してくれてありがとう - 私はこれがかなりの人を焼いたと確信しています。 –

+0

@ user986065:そうですね、このような場合は、デフォルトでプレースホルダの値(通常は 'None')を使用し、関数の本体でチェックすることをお勧めします(例:' aがNoneの場合:a = [] ')。 – voithos

関連する問題