具有互斥可选参数的python类/子类,使用超类的实例作为可能的构造函数

时间:2012-10-29 13:28:19

标签: python optional-parameters

我试图在python中定义一个B类,即A的子类,它可以接受多种实例化方式,非常灵活。 A是一个简单的类,成员很少。我知道如何编写A以允许混合使用位置/关键字参数,并且如果省略某些参数则使用默认值。

我的问题来自B班.B只是带有额外成员的A.但是当我创建B的实例时,我希望在:

之间做出选择
  • 由混合的位置/关键字参数创建的实例(非常类似于A)
  • 创建的实例,指定额外成员和A
  • 的现有实例(或副本)
  • 仅使用现有的A实例创建,额外成员获取默认值。
  • 互斥使用现有的A和位置/关键字参数

编辑:类似这样的事情

class A:
    def __init__(self, x1=1, x2='a', x3=4.0)
        self.x1=x1
        self.x2=x2
        self.x3=x3

class B(A):
    def __init__(self, x1=1, x2='a', x3=4.0, x4='t')
        self.x4=x4
        A.__init__(x1,x2,x3)

然后我想像这样使用它:

a1=A()
b1=B()         # takes all defaults
b2=B(x4='r')   # x1,x2,x3 gets defaults from A
b3=B(a1,x4='z')  # use a1, an instance of A
b4=B(x1,x2,x3,x4) # defines manually all arguments
b5=B(a1,x1=2) # this one should not work because x1 can come from the instance a1 or x1

2 个答案:

答案 0 :(得分:2)

最简单的事情可能是使用与B使用相同签名的简单初始化程序来定义A,然后将其他工厂函数定义为类方法来执行更复杂的方案。这样,当两种不同的构造方法实际上完全无法区分时,你就不会搞砸了。

类似于:

class B(A):
    def __init__(self, some, args):
        A.__init__(self, some, args)

    @classmethod
    def fromA(cls, theA, extra=some_default):
        newB = cls(theA.some, theA.args)
        newB.extra = extra
        return newB

答案 1 :(得分:0)

根据我的经验,处理这类复杂案例的最佳方法是使用*args, **kwargs并通过一系列条件手动处理它们,例如B.__init__

if isinstance(arg[0], A):
    if has_other_args:
        raise TypeError
    else:
        do_something()
else:
    do_something_else()

然而,这仍然会变得非常复杂,所以工厂功能(如Duncan所建议的)可能是最好的方法。

旁注:每当我发现自己处于想要这种功能的位置时,通常表明我的设计不对。即使我实现它,我通常最终会用更整洁的东西替换整个结构。