У вас есть проблема с этими циклами:
for k, v in kwargs.items():
setattr(self, k, v)
У вас есть по одному в каждом классе, и это означает, что каждый один из классов устанавливает все ключевое слово аргументы в качестве атрибутов self
.
Когда этот цикл выполняется в A
, он завершается ошибкой, поскольку B
имеет свойство, которое необходимо инициализировать, прежде чем он сможет работать.
Как вы отметили в этом вопросе, быстрое решение проблемы - убедиться, что B
устанавливает свой словарь до того, как он запустит A.__init__
:
class B(A):
def __init__(self, **kwargs):
_b = {} # set this up first
A.__init__(self, **kwargs) # before calling the superclass
for k, v in kwargs.items():
setattr(self, k, v)
Но, вероятно, есть лучший подход, который позволит вам избежатьизбыточные петли.Я бы предложил явно назвать ключевые аргументы, которые вы ожидаете в каждом классе.Таким образом, b
будет виден только классу B
, а не A
и C
(кроме как часть kwargs
).
class A:
def __init__(self, *, a): # a is keyword-only arg, no kwargs accepted here
self.a = a
class B:
def __init__(self, *, b, **kwargs):
super().__init__(**kwargs) # doesn't mess with b!
self._b = {}
self.b = b
@property
def b(self):
...
class C:
def __init__(self, *, c, **kwargs):
super().__init__(**kwargs)
self.c = c
Теперь вы можете позвонить C(a="foo", b={1: 2}, c="bar")
и каждый класс будет обращать внимание только на атрибут, который ему нужен.