class method generates "TypeError: ... got multiple values for keyword argument ..."

If I define a class method with a keyword argument thus:

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

calling the method generates a TypeError:

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

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

What's going on?


Solution 1:

The problem is that the first argument passed to class methods in python is always a copy of the class instance on which the method is called, typically labelled self. If the class is declared thus:

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

it behaves as expected.

Explanation:

Without self as the first parameter, when myfoo.foodo(thing="something") is executed, the foodo method is called with arguments (myfoo, thing="something"). The instance myfoo is then assigned to thing (since thing is the first declared parameter), but python also attempts to assign "something" to thing, hence the Exception.

To demonstrate, try running this with the original code:

myfoo.foodo("something")
print
print myfoo

You'll output like:

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

<__main__.foo object at 0x321c290>

You can see that 'thing' has been assigned a reference to the instance 'myfoo' of the class 'foo'. This section of the docs explains how function arguments work a bit more.

Solution 2:

Thanks for the instructive posts. I'd just like to keep a note that if you're getting "TypeError: foodo() got multiple values for keyword argument 'thing'", it may also be that you're mistakenly passing the 'self' as a parameter when calling the function (probably because you copied the line from the class declaration - it's a common error when one's in a hurry).