Как добавить аргументы ключевого слова в конструктор производного класса в Python?

Я хочу добавить аргументы ключевого слова в производный класс, но не могу понять, как это сделать. Попытка очевидного

class ClassA(some.package.Class):

    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)

class ClassB(ClassA):

    def __init__(self, *args, a='A', b='B', c='C', **kwargs):
        super(ClassB, self).__init__(*args, **kwargs)
        self.a=a
        self.b=b
        self.c=c

не удается, потому что я не могу перечислить такие параметры для ClassB ' s __init__. И

class ClassB(ClassA):

    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)
        self.a=a
        self.b=b
        self.c=c

конечно не работает, потому что новые ключевые слова не указаны.

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

4 ответов


попробуйте сделать так:

class ClassA(object):
    def __init__(self, *args, **kwargs):
        pass

class ClassB(ClassA):
    def __init__(self, *args, **kwargs):            
        self.a = kwargs.pop('a', 'A')
        self.b = kwargs.pop('b', 'B')
        self.c = kwargs.pop('c', 'C')
        super(ClassB, self).__init__(*args, **kwargs)

эффективно вы добавляете аргументы ключевого слова a, b и c в ClassB, передавая другие аргументы ключевого слова в ClassA.


все, что вам нужно сделать, это переставить аргументы.

def __init__(self, a='A', b='B', c='C', *args, **kwargs):

эффект def __init__(self, a='A', b='B', c='C', *args, **kwargs):

изменение кода OP с помощью конструктора дочернего класса, имеющего вышеуказанную подпись:

class BaseClass(object):
    def __init__(self, *args, **kwargs):
        self.args = args
        for k, v in kwargs.items():
            setattr(self, k, v)

class ClassA(BaseClass):
    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)

class ClassB(ClassA):
    def __init__(self, a='A', b='B', c='C', *args, **kwargs):
        self.a = a
        self.b = b
        self.c = c
        super(ClassA, self).__init__(*args, **kwargs)


A = ClassA('hello', 'world', myname='hal',myemail='hal@hal.hal')
B = ClassB('hello', 'world', myname='hal', myemail='hal@hal.hal')

print("CLASS A:", A.__dict__)
print("CLASS B:", B.__dict__)
# yields the following:
CLASS A: {'args': ('hello', 'world'), 'myname': 'hal', 'myemail': 'hal@hal.hal'}
CLASS B: {'args': (), 'myname': 'hal', 'a': 'hello', 'myemail': 'hal@hal.hal', 'c': 'C', 'b': 'world'}

код не будет выдавать исключение, однако a, b & c теперь позиционно являются первыми 3 аргументами, переданными методу (игнорируя self), как видно из двух диктов объекта.

доступ к атрибутам a, b & c показывает это другой эффект

>>> B.a # expect to see 'A'
'hello'
>>> B.b # similarly
'world'
>>> B.c # but this retails the default value
'C'

AFAIK, вы не можете добавить только новое ключевое слово аргументы для подписи метода. Пожалуйста, поправьте меня, если я ошибаюсь.

однако @aknuds1 и @Ole Prypin предоставили решения, которые эффективно добавляют новые аргументы ключевого слова в дочерний класс. Решение Олега немного умнее,но мне легче понять версию aknuds1.

  • поп-элементы из kwargs dict, объединенный со значением по умолчанию
  • назначить атрибуту экземпляра с помощью setattr
  • вызов родителей конструктор с args, kwargs

Используйте Python 3.x, что делает допустимыми аргументы только для ключевых слов.

или используйте этот обходной путь...

class ClassB(ClassA):
    def __init__(self, *args, **kwargs):
        for arg, default in [('a', 'A'), ('b', 'B'), ('c', 'C')]:
            setattr(self, arg, kwargs.pop(arg, default))
        super(ClassA, self).__init__(*args, **kwargs)