クラスメソッドは「TypeError:…キーワード引数に複数の値を取得しました…」を生成します


129

キーワード引数を使用してクラスメソッドを定義すると、次のようになります。

class foo(object):
  def foodo(thing=None, thong='not underwear'):
    print thing if thing else "nothing" 
    print 'a thong is',thong

メソッドを呼び出すと、生成さTypeError

myfoo = foo()
myfoo.foodo(thing="something")

...
TypeError: foodo() got multiple values for keyword argument 'thing'

どうしたの?


1
なぜself暗黙より明示が優れているのかについて満足のいく答えは得られませんthis
nurettin 2018

回答:


163

問題は、Pythonのクラスメソッドに渡される最初の引数が常に、メソッドが呼び出されるクラスインスタンスのコピーであり、通常はというラベルが付いていることselfです。クラスがこのように宣言されている場合:

class foo(object):
  def foodo(self, thing=None, thong='not underwear'):
    print thing if thing else "nothing" 
    print 'a thong is',thong

期待どおりに動作します。

説明:

self最初のパラメータとして指定しない場合、myfoo.foodo(thing="something")が実行されると、foodoメソッドは引数を指定して呼び出されます(myfoo, thing="something")。インスタンスはmyfoo、その後に割り当てられているthing(以降thing最初の宣言されたパラメータである)が、Pythonはまた、割り当てようと"something"するthing例外したがって、。

実例として、これを元のコードで実行してみてください。

myfoo.foodo("something")
print
print myfoo

次のように出力されます:

<__main__.foo object at 0x321c290>
a thong is something

<__main__.foo object at 0x321c290>

「thing」には、クラス「foo」のインスタンス「myfoo」への参照が割り当てられていることがわかります。ドキュメントのこのセクションでは、関数の引数がどのように機能するかを説明します。


1
注:関数の定義に最初のパラメーターとしてselfが含まれている場合、同じタイプのエラーが発生する可能性があり、誤って最初のパラメーターとしてselfを指定して関数を呼び出します。
クリストファーハンター

48

有益な投稿をありがとう。「TypeError:foodo()がキーワード引数 'thing'に複数の値を取得しました」を取得している場合、次の場合に誤って「self」をパラメーターとして渡している可能性があることに注意してください関数を呼び出す(おそらくクラス宣言から行をコピーしたため-急いでいるときは一般的なエラーです)。


7
それが私に起こったことです、この答えに追加してくれてありがとう。これは、よくある間違いである可能性があります。そのため、あなたは私の賛成票を得ています。
rdrey

同じことがオーバーロードするときに発生@classmethod溶液を使用することsuper().function(...)の代わりに<parentclass>.function(cls, ...)
ederag 2016

30

これは明白かもしれませんが、これまでにそれを見たことがない人を助けるかもしれません。これは、通常の関数でも、位置と名前でパラメーターを誤って割り当てた場合にも発生します。

>>> def foodo(thing=None, thong='not underwear'):
...     print thing if thing else "nothing"
...     print 'a thong is',thong
...
>>> foodo('something', thing='everything')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foodo() got multiple values for keyword argument 'thing'

6

関数に「staticmethod」デコレータを追加するだけで問題が修正されます

class foo(object):
    @staticmethod
    def foodo(thing=None, thong='not underwear'):
        print thing if thing else "nothing" 
        print 'a thong is',thong

このエラーが発生し、この解決策で問題が解決しました。しかし、このデコレータが問題をどのようにまたはなぜ解決したかについて詳しく説明できますか?
レイ

1
staticmethodは、最初の引数として自分自身を受け取るメソッドを停止します。したがって、を呼び出すとmyfoo.foodo(thing="something")、暗黙の自己引数ではなく、thing = "something"が最初の引数に割り当てられます。
danio 2016

また、通常はアクセスされる関数内のクラス変数にアクセスできないことも意味しますself
drevicko

4

もう1つ回答を追加したいと思います。

関数の呼び出しで、キーワード引数と共に誤った位置順序で位置パラメーターを渡そうとすると発生します。

there is difference between parameter and argumentあなたはここでPythonの引数とパラメータについて詳しく読むことができます

def hello(a,b=1, *args):
   print(a, b, *args)


hello(1, 2, 3, 4,a=12)

3つのパラメーターがあるため:

aは位置パラメータです

b = 1はキーワードおよびデフォルトパラメータです

* argsは可変長パラメーターです

したがって、最初にを位置パラメーターとして割り当てます。つまり、位置引数に位置順序で値を提供する必要があります。ここでは順序が重要です。ただし、呼び出し関数のaの場所に引数1を渡してから、に値を提供し、キーワード引数として扱います。現在、2つの値があります。

1つは位置値です:a = 1

2番目はa = 12であるキーワード値です

解決

に変更する必要hello(1, 2, 3, 4,a=12)があるhello(1, 2, 3, 4,12) ので、aは1の位置値のみを取得し、bは値2を取得し、残りの値は* args(可変長パラメーター)を取得します。

追加情報

* argsが2,3,4を取得し、aが1を取得し、bが12を取得する必要がある場合

そして、私たちはこのようにすることができます
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)

もっと何か :

def hello(a,*c,b=1,**kwargs):
    print(b)
    print(c)
    print(a)
    print(kwargs)

hello(1,2,1,2,8,9,c=12)

出力:

1

(2, 1, 2, 8, 9)

1

{'c': 12}

これは既に回答stackoverflow.com/a/31822875/12663でカバーされています-あなたの例には、同じパラメーター(a)が位置と名前によって明示的に割り当てられています。
danio 2016

3

このエラーは、キーの1つが位置引数に似ている(同じ文字列名を持つ)キーワード引数を渡した場合にも発生する可能性があります。

>>> class Foo():
...     def bar(self, bar, **kwargs):
...             print(bar)
... 
>>> kwgs = {"bar":"Barred", "jokes":"Another key word argument"}
>>> myfoo = Foo()
>>> myfoo.bar("fire", **kwgs)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() got multiple values for argument 'bar'
>>> 

「火」は「棒」の議論に受け入れられました。そして、まだkwargsに存在する別の「バー」引数があります。

メソッドに渡す前に、キーワード引数をクワーグスから削除する必要があります。


1

また、jquery ajaxを使用して「リクエスト」パラメータを含まない関数に逆のURLを使用している場合、これはDjangoで発生する可能性があります

$.ajax({
  url: '{{ url_to_myfunc }}',
});


def myfunc(foo, bar):
    ...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.