sınıf yöntemi "TypeError:… anahtar kelime bağımsız değişkeni için birden çok değer aldı…" oluşturur


129

Anahtar kelime bağımsız değişkeniyle bir sınıf yöntemi tanımlarsam, şöyle:

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

yöntemi çağırmak bir TypeError:

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

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

Neler oluyor?


2
Açıklığın neden selförtük olmaktan daha iyi olduğu konusunda asla tatmin edici bir yanıt alamayacaksınız this.
nurettin

Yanıtlar:


165

Sorun, python'da sınıf yöntemlerine iletilen ilk argümanın her zaman yöntemin çağrıldığı, tipik olarak etiketlendiği sınıf örneğinin bir kopyası olmasıdır self. Sınıf böyle bildirilirse:

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

beklendiği gibi davranır.

Açıklama:

selfİlk parametre olmadan myfoo.foodo(thing="something")çalıştırıldığında, foodoyöntem argümanlarla çağrılır (myfoo, thing="something"). Örnek myfoodaha sonra atanan thing(beri thingilk kez açıklandığı parametredir) değil, aynı zamanda piton girişimleri atamak "something"için thingbu nedenle özel durum,.

Göstermek için, bunu orijinal kodla çalıştırmayı deneyin:

myfoo.foodo("something")
print
print myfoo

Şöyle çıktı alacaksınız:

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

<__main__.foo object at 0x321c290>

Bu 'şey'e' foo 'sınıfının' myfoo 'örneğine bir referans atandığını görebilirsiniz. Dokümanların bu bölümü fonksiyon argümanlarının nasıl biraz daha fazla çalıştığını açıklıyor.


1
not: Eğer fonksiyon def'iniz ilk parametre olarak self'i içeriyorsa ve daha sonra yanlışlıkla fonksiyonu birinci parametre olarak self ile çağırırsanız, aynı tür hatayı alabilirsiniz.
Christopher Hunter

48

Öğretici gönderiler için teşekkürler. "TypeError: foodo () anahtar kelime bağımsız değişkeni 'şey' için birden fazla değere sahipse" şunu not etmek isterim ki, aynı zamanda yanlışlıkla bir parametre olarak 'self'i geçiriyor olabilirsiniz işlevi çağırmak (muhtemelen satırı sınıf bildiriminden kopyaladığınız için - aceleniz olduğunda yaygın bir hatadır).


7
Bana olan buydu, bu yanıta eklediğin için teşekkürler. Bu, yapılacak en yaygın hata olabilir, bu yüzden benim olumlu oyumu alıyorsunuz.
rdrey

Aynı şey bir aşırı yüklenirken de meydana gelir @classmethod, çözümsuper().function(...) yerine kullanmaktır <parentclass>.function(cls, ...).
ederag

30

Bu açık olabilir, ancak daha önce hiç görmemiş birine yardımcı olabilir. Bu, yanlışlıkla bir parametreyi konuma göre ve açıkça ada göre atarsanız, normal işlevler için de olur.

>>> 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

sadece çalışmak için 'statik yöntem' dekoratörünü ekleyin ve sorun giderildi

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

Bu hatayı yeni aldım ve bu çözüm sorunumu çözdü. Ancak bu dekoratörün sorunu nasıl veya neden çözdüğünü açıklayabilir misiniz?
Ray

1
staticmethod ilk argüman olarak self'i alan yöntemi durdurur. Öyleyse, şimdi çağırırsanız myfoo.foodo(thing="something"), birinci argümana örtük öz argüman yerinething = "bir şey" atanacak.
danio

bu ayrıca, genellikle şu self
adresten

4

Bir cevap daha eklemek istiyorum:

Fonksiyon çağırırken anahtar kelime argümanı ile birlikte yanlış pozisyon sırasına sahip konumsal parametreyi geçirmeye çalıştığınızda olur.

there is difference between parameter and argumentPython'da Argümanlar ve Parametreler hakkında ayrıntılı olarak okuyabilirsiniz.

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


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

Üç parametremiz olduğu için:

a konumsal bir parametredir

b = 1, anahtar kelime ve varsayılan parametredir

* args değişken uzunluk parametresidir

bu yüzden ilk önce bir konumsal parametre olarak bir atarız, yani konumsal argümana konum sırasına göre değer sağlamamız gerekir, burada sıra önemlidir. ancak fonksiyon çağırırken a'nın yerine 1 argümanını geçiriyoruz ve sonra a'ya değer de veriyoruz, anahtar kelime argümanı olarak ele alıyoruz. şimdi a'nın iki değeri var:

biri konumsal değerdir: a = 1

ikincisi, a = 12 olan anahtar kelimeli değerdir

Çözüm

Şimdi değiştirmemiz hello(1, 2, 3, 4,a=12)gerekiyor, hello(1, 2, 3, 4,12)şimdi a sadece 1 olan bir konumsal değer alacak ve b 2 değerini alacak ve geri kalan değerler * args (değişken uzunluk parametresi) alacak

ek bilgi

* args'ın 2,3,4 olmasını ve a'nın 1 ve b'nin 12 almasını istiyorsak

o zaman böyle yapabiliriz
def hello(a,*args,b=1): pass hello(1, 2, 3, 4,b=12)

Bir şey daha :

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

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

çıktı :

1

(2, 1, 2, 8, 9)

1

{'c': 12}

bu yanıt stackoverflow.com/a/31822875/12663 kapsamındadır - örneğinizde aynı parametre (a) konum tarafından ve ayrıca açıkça adla atanmıştır.
danio

3

Bu hata, anahtarlardan birinin benzer olduğu (aynı dize adına sahip) bir anahtar sözcük argümanını konumsal bir argümana ilettiğinizde de ortaya çıkabilir.

>>> 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'
>>> 

"bar" argümanına "ateş" kabul edildi. Ve yine de kwarglarda mevcut olan başka bir 'bar' argümanı var.

Yönteme geçmeden önce anahtar kelime argümanını kwarg'lardan kaldırmanız gerekir.


1

Ayrıca, 'request' parametresi içermeyen bir işleve geri dönen url için jquery ajax kullanıyorsanız Django'da da bu olabilir.

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


def myfunc(foo, bar):
    ...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.