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



我正在尝试在A类B类中定义A的A类子类,这些子类可以接受多种实例化的方法,以非常灵活。A是一个简单的课程,很少会成员。我知道如何编写一个以允许位置/关键字参数的混合,如果省略了某些参数,则具有默认值。

我的问题是B级。B只是一个额外的成员。但是,当我创建B的实例时,我想在以下方面选择:

  • 由位置/关键字参数的组合创建的实例(几乎像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

最简单的事情可能是用具有与A使用相同的签名的不错的直接启动器来定义B,然后定义其他出厂功能,将其定义为类方法,以执行更复杂的场景。这样,当两种不同的施工方法实际上完全没有可区分的论点时,您就不会搞砸了。

所以类似:

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

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

)手动处理它们。
if isinstance(arg[0], A):
    if has_other_args:
        raise TypeError
    else:
        do_something()
else:
    do_something_else()

但是,这仍然可能变得非常复杂,因此工厂功能(如邓肯的建议)可能是最好的方法。

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

最新更新