2

Are keyword arguments handled somehow specially in inherited methods?

When I call an instance method with keyword arguments from the class it's defined in, all goes well. When I call it from a subclass, Python complains about too many parameters passed.

Here's the example. The "simple" methods don't use keyword args, and inheritance works fine (even for me :-) The "KW" methods use keyword args, and inheritance doesn't work anymore... at least I can't see the difference.

class aClass(object):
  def aSimpleMethod(self, show):
    print('show: %s' % show)
  def aKWMethod(self, **kwargs):
    for kw in kwargs:
      print('%s: %s' % (kw, kwargs[kw]))

class aSubClass(aClass):
  def anotherSimpleMethod(self, show):
    self.aSimpleMethod(show)
  def anotherKWMethod(self, **kwargs):
    self.aKWMethod(kwargs)

aClass().aSimpleMethod('this')
aSubClass().anotherSimpleMethod('that')
aClass().aKWMethod(show='this')

prints this, that, and this, as I expected. But

aSubClass().anotherKWMethod(show='that')

throws:

TypeError: aKWMethod() takes exactly 1 argument (2 given)
virtualnobi
  • 1,140
  • 2
  • 11
  • 35

3 Answers3

1

You need to use **kwargs when you call the method, it takes no positional args, just keyword arguments:

 self.aKWMethod(**kwargs)

Once you do, it works fine:

In [2]: aClass().aSimpleMethod('this')
   ...: aSubClass().anotherSimpleMethod('that')
   ...: aClass().aKWMethod(show='this')
   ...: 
show: this
show: that
show: this
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
1

When you do self.aKWMethod(kwargs), you're passing the whole dict of keyword arguments as a single positional argument to the (superclass's) aKWMethod method.

Change that to self.aKWMethod(**kwargs) and it should work as expected.

Tom Dalton
  • 6,122
  • 24
  • 35
1

Just to demonstrate in the simplest terms possible what is going wrong, note that this error has nothing to do with inheritance. Consider the following case:

>>> def f(**kwargs):
...     pass
...
>>> f(a='test') # works fine!
>>> f('test')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 0 positional arguments but 1 was given

The point is that **kwargs only allows keyword arguments and cannot be replaced by a positional argument.

brianpck
  • 8,084
  • 1
  • 22
  • 33