2017-02-23 7 views
0

* argsを使用してメソッドを呼び出す方法がいくつか異なります。以下は私のコードです。TypeErrorを理解する:キーワード引数に複数の値がある

def total(name, *args): 
    if args: 
     print("%s has total money of Rs %d/- " %(name, sum(args))) 
    else: 
     print("%s's piggy bank has no money" %name) 

ここでは、このメソッドを呼び出す方法が2つあります。 1つは*()の中に余分な引数を渡すか、カンマで直接区切ります。私はparam = valueの形で 'name'の値を意図的に渡しているので、エラーが出ます。

1 - - を分離余分のparamsコンマを渡す: -

>>> total(name="Adi", 1, 2, 10) 
    File "<stdin>", line 1 
SyntaxError: non-keyword arg after keyword arg 

2 - 使い方*()余分のparamsを渡す: -

>>> total(name="Adi", *(1, 2, 10)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: total() got multiple values for keyword argument 'name' 

私がしようとしていた二つの方法を以下に示します最初のエラーメッセージはかなり明確で、正確なエラーを伝えます。しかし、私は2番目の呼び出しのエラーメッセージを理解することができません。

どのようにPythonは、パラメータ「名前」に複数の値を取得していますという2番目のコールを評価していますか?次のように私の心に来た可能性のある方法は、内部的にPythonは

total(name="Adi", *(1, 2, 10))

を変換されますされています - これ以上の翻訳で

total(*(1, 2, 10), name="Adi")

、位置ごとに、「名前は」の値を取得します*(1 、2,10)、後で再び「Adi」となる。したがって、複数の値の誤差が理解されます。

しかし、私はPythonが内部的に位置を変更するかどうか、わかりませんか?これについての洞察は役に立ちます。

+0

'合計(品名 - "アディ"、1、2、10)'ための有効でありません' - '記号を使用します。本当のコードを表示していますか? –

+0

私の悪い。ミスだった。 –

答えて

1

私はinspectモジュールを使用する方法を視察。 inspectモジュールのgetcallargs()メソッドは、渡された値のメソッドの引数へのマッピングを提供します。

def total(name, *args): 
    if args: 
     print("%s has total money of Rs %d/- " %(name, sum(args))) 
    else: 
     print("%s's piggy bank has no money" %name) 

#total(name="Adi", *(1, 2, 10)) 
# equivalent call using inspect module 
import inspect 
print inspect.getcallargs(total, 'Adi', *(1, 2, 10)) 

だから、メソッドの呼び出しが行われたとき、渡されるすべての引数は、次の二つの形式

*positional :- a tuple of all positional arguments (without keyword) and arguments passed within *() or the extra non-keyworded arguments

**named :- a dictionary of all the arguments passed in form of param=value, and extra keyworded arguments

だから私のコールtotal(name="Adi", *(1, 2, 10))で、'positional'タプルが値を持っている(1のいずれかに行きます

それは引数への値の割り当てを行う:2,10)と'named'辞書は値{「アディ」「名称」}有します。割り当て時に、強制的な議論が最初に割り当てられます。 Pythonは強制引数(ここでは['name'])のリストをチェックし、'positional'タプルの値を順番に割り当てます。未割り当てのタプルからの値は、余分なパラメータ(キーワード以外の引数)とみなされます。

したがってパラメーター'name'は、それに割り当てられた値1を取得します。残りの値(2と10)は余分なパラメータと見なされます。この方法は、それの署名非キーワードとして引数を有する場合

次に、それは、チェック。その場合、'positional'タプルの残りの値が同じタプルに割り当てられます。したがってここで'args'は、残りの値、すなわち(2,10)のタプルに割り当てられます。

しかし、メソッドシグネチャにキーワード以外の引数がなく、'positional'タプルに未割り当ての値が残っていると、pythonは「メソッドはX引数Yを指定したときにYを返します」というエラーをスローします。

'positional'の値がすべて割り当てられると、'named'ディクショナリからの値の割り当てが割り当てられます。この場合、インタプリタは、強制的な引数のいずれかが辞書に存在するかどうか、すなわち、強制的な引数のいずれかの値がメソッド呼び出しの<param=value>の形式で渡されるかどうかをまずチェックします。はいの場合、次に、'positional'タプルからの値の割り当て中に、それらの強制引数に値が割り当てられているかどうかを確認します。

もしそうなら、それは同じ引数('positional'からのものと'named'からのもの)の2つの値を見つけて、"got multiple values for keyword argument"というエラーをスローします。それ以外の場合は、'named'辞書の引数に値を割り当てます。

このように、メソッド呼び出しでname="Adi"を渡したので、上記の場合、引数'name'は強制的な引数であり、'named'辞書に存在します。位置値('positional'タプルからの値)の割り当て中に、変数'name'に値1が割り当てられています。そして、名前付き引数の辞書('named'の値の辞書)からは、値「Adi」が得られ、2つの値が変数'name'に割り当てられます。そこで我々は、エラーを取得している: -

total() got multiple values for keyword argument 'name'

をしたがって、非キーワードとして追加の引数を渡しながら、一つはちょうどそれが位置になります強制引数の値を渡す必要があります。しかし、<param=val>の形式ではなく、それは名前をつけて、パラメータの2つの値を取得するので、エラーがスローされます。したがって、強制的な引数を<param = value >の形式で渡すことはお勧めしません。

だからメソッドを呼び出すための正しい方法である: -

total('Adi', *(1,2,10))

又は

total('Adi', 1, 2, 10)

関連する問題