Я пытаюсь использовать композицию над концепцией дизайна наследования, и я сохраняю создателя и main_actor для каждого компонента. Это выглядит очень повторяющимся и уродливым, поэтому мне интересно, есть ли способ сделать его приятнее.
class ComponentA:
def __init__(self, **kwargs):
self.creator = kwargs['creator']
self.main_actor = kwargs['main_actor']
self.b = ComponentB(creator=self, main_actor=self.main_actor)
self.c = ComponentC(creator=self, main_actor=self.main_actor)
# instead of that, i want to achieve the same,
# without the eye sore of the repetitive kwargs:
self.b = ComponentB()
self.c = ComponentC()
# perhaps with metaclasses? or a function?
self.b = make(ComponentB)
self.c = make(ComponentC)
Их состав и наследование имеют свое место. Чтобы избежать повторения в ваших классах компонентов, я бы использовал наследование таким образом:
class Component(object):
def __init__(self, **kwargs):
for name in ('creator', 'main_actor'):
setattr(self, name, kwargs[name])
component_class = type(self)
for attr in dir(component_class):
if not attr.startswith('__'):
sub_component_class = getattr(component_class, attr)
if issubclass(sub_component_class, Component):
setattr(self, attr, sub_component_class(**{**kwargs, 'creator': self}))
class ComponentB(Component):
pass
class ComponentC(Component):
pass
class ComponentA(Component):
b = ComponentB
c = ComponentC
# In [0]: a = ComponentA(creator='me', main_actor='fred')
#
# In [1]: a.creator
# Out[1]: 'me'
#
# In [2]: a.b
# Out[2]: <__main__.ComponentB at 0x7f6def403550>
#
# In [3]: a.b.creator
# Out[3]: <__main__.ComponentA at 0x7f6def47cc18>
#
# In [4]: a.b.main_actor
# Out[4]: 'fred'
#
# In [5]: a.c.main_actor
# Out[5]: 'fred'
Я не уверен, как это pythonic, но вы можете попробовать следующее:
class ComponentA:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
self.b = self.make(ComponentB)
self.c = self.make(ComponentC)
def make(self, component):
return component(creator=self, main_actor=self.main_actor)
class ComponentB:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
class ComponentC:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
a = ComponentA(creator=None, main_actor='MAIN_ACTOR')
print(a.b.main_actor)
>>> 'MAIN_ACTOR'
Редактировать: Смотрите ли я.__ dict __. обновление (** kwargs) хорошего или плохого стиля? для получения дополнительной информации об этом решении.