我试图在python中定义一个B类,即A的子类,它可以接受多种实例化方式,非常灵活。 A是一个简单的类,成员很少。我知道如何编写A以允许混合使用位置/关键字参数,并且如果省略某些参数则使用默认值。
我的问题来自B班.B只是带有额外成员的A.但是当我创建B的实例时,我希望在:
之间做出选择编辑:类似这样的事情
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
答案 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所建议的)可能是最好的方法。
旁注:每当我发现自己处于想要这种功能的位置时,通常表明我的设计不对。即使我实现它,我通常最终会用更整洁的东西替换整个结构。