Функция Python 2.7 с аргументами ключевого слова в суперклассе: как получить доступ из подкласса?

#python #python-2.7 #inheritance #variadic

#python #python-2.7 #наследование #переменный

Вопрос:

Обрабатываются ли аргументы ключевого слова каким-то образом специально в унаследованных методах?

Когда я вызываю метод экземпляра с аргументами ключевого слова из класса, в котором он определен, все идет хорошо. Когда я вызываю его из подкласса, Python жалуется на слишком много переданных параметров.

Вот пример. «Простые» методы не используют аргументы ключевых слов, и наследование работает нормально (даже для меня 🙂 Методы «KW» используют аргументы ключевых слов, и наследование больше не работает … по крайней мере, я не вижу разницы.

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

печатает this , that , и this , как я и ожидал. Но

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

бросает:

 TypeError: aKWMethod() takes exactly 1 argument (2 given)
  

Ответ №1:

Когда вы это делаете self.aKWMethod(kwargs) , вы передаете весь список аргументов ключевого слова в виде одного позиционного аргумента методу (суперкласса) aKWMethod .

Измените это на self.aKWMethod(**kwargs) , и оно должно работать так, как ожидалось.

Ответ №2:

Вам нужно использовать ** kwargs при вызове метода, он не принимает позиционных аргументов, только аргументы ключевого слова:

  self.aKWMethod(**kwargs)
  

Как только вы это сделаете, все будет работать нормально:

 In [2]: aClass().aSimpleMethod('this')
   ...: aSubClass().anotherSimpleMethod('that')
   ...: aClass().aKWMethod(show='this')
   ...: 
show: this
show: that
show: this
  

Ответ №3:

Просто чтобы продемонстрировать в самых простых терминах, что происходит не так, обратите внимание, что эта ошибка не имеет ничего общего с наследованием. Рассмотрим следующий случай:

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

Дело в том, что разрешены **kwargs только аргументы ключевого слова и не могут быть заменены позиционным аргументом.