使用默认参数清除pythonic组合

时间:2018-10-02 17:42:26

标签: python design-patterns constructor default-value composition

假设我想组成两个对象,并且希望能够定义多个尊重默认参数的构造函数。

class A:
   def __init__(x,y=0):
       self.x = x
       self.y = y

class B:
    def __init__(w,objA, z=1):
         self.w = w
         self.objA = objA
         self.z = z

我想为B使用多个构造函数,这些构造函数允许我传递对象A或传递参数,然后构造A。看着What is a clean, pythonic way to have multiple constructors in Python?,我可以做到:

class B:
    def __init__(w, objA, z=1):
         self.w = w
         self.objA = objA
         self.z=z

    @classmethod
    def from_values(cls,w,z,x,y):
        objA = A(x,y)
        return cls(w,objA,z)

问题在于默认值已被覆盖,我想保留它们。以下内容当然不起作用。

@classmethod
def from_values(cls,w,x,**kwargs):
    objA = A(x,**kwargs)
    return cls(w,objA,**kwargs)

所以看来我很想记住默认值并像这样调用它们

@classmethod
def from_values(cls,w,x,z=1,y=0):
    objA = A(x,y)
    return cls(w,objA,z)

这不是我想要的,因为我希望对象自己处理默认值,而不必强迫他们记住默认值。我可以做一个比上述更好的方法并使用:

 @classmethod
 def from_values(cls,w,x,z=1,**kwargs):
    objA = A(x,**kwargs)
    return cls(w,objA,z)

但是在这种情况下,我仍然需要“记住” z的默认值。是否有Pythonic解决方案?这是设计问题吗?有人可以指出我的良好设计模式或最佳做法吗?用多个对象组成时,这个问题变得更加复杂...

class L:
    def __init__(objM,objN):
        self.objM = objM
        self.objN = objN

    @classmethod
    def from_values(cls, m1,m2,m3,n1,n2):
        objM = M(m1,m2,m3)
        objN = N(n1,n2)
        return cls(objM, objN)

1 个答案:

答案 0 :(得分:0)

首先,我认为这不是您想要的。随着规模的扩大,尝试调用构造函数将很乏味且容易出错。

您可以使用显式词典解决我们两个问题。

class A:
    def __init__(self, config):
        self.x = config.get('x')
        assert self.x  # if you need it
        self.y = config.get('y', 0)

class B:
    def __init__(self, b_config, objA):
        self.w = b_config.get('w')
        self.objA = objA
        self.z = b_config.get('z', 1)

    @classmethod
    def from_values(cls,b_config,a_config):
        return cls(b_config, A(a_config))

B.from_values({'w':1, 'z':2}, {'x': 3, 'y': 4})

它可能不像您想要的那样聪明或整洁,但是它确实允许您从A进行构造(如果已经拥有),或者以结构化的方式传递一组可配置的参数方式。