如何在类实例化上自动传递重复的kwarg

时间:2018-10-18 01:01:00

标签: python

我试图在继承设计概念上使用组合,并且一直在存储每个组件的创建者和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)

2 个答案:

答案 0 :(得分:0)

我不确定这是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'

编辑:有关此解决方案的更多信息,请参见Is self.__dict__.update(**kwargs) good or poor style?

答案 1 :(得分:0)

组成和继承都应有的地位。为了避免在组件类中重复,我将使用继承:

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'