Python 中基于参数的条件继承

Adi*_*iva 6 python oop inheritance

作为 OOP 的新手,我想知道是否有任何方法可以根据子类在 Python 中的调用方式继承多个类之一。我尝试这样做的原因是因为我有多个同名的方法,但在三个具有不同功能的父类中。在创建对象时,必须根据某些条件继承相应的类。

例如,我试图根据实例化时是否传递任何参数来使C类继承A或B,但没有成功。谁能建议更好的方法来做到这一点?

class A:
    def __init__(self,a):
        self.num = a

    def print_output(self):
        print('Class A is the parent class, the number is 7',self.num)

class B:
    def __init__(self):
        self.digits=[]

    def print_output(self):
        print('Class B is the parent class, no number given')

class C(A if kwargs else B):
    def __init__(self,**kwargs):
        if kwargs:
            super().__init__(kwargs['a'])
        else:
            super().__init__()

temp1 = C(a=7)
temp2 = C()

temp1.print_output()
temp2.print_output()
Run Code Online (Sandbox Code Playgroud)

所需的输出将是“A 类是父类,编号是 7”,后跟“B 类是父类,没有给出编号”。

谢谢!

Boo*_*boo 7

无论您是刚刚开始接触 OOP 还是已经使用了一段时间,我都建议您阅读一本关于设计模式的好书。Gamma 的《设计模式》是一个经典之作。舵。约翰逊和弗利赛德斯。

您可以使用带有委托的组合,而不是使用继承。例如:

class A:
    def do_something(self):
        # some implementation

class B:
    def do_something(self):
        # some implementation

class C:
    def __init__(self, use_A):
        # assign an instance of A or B depending on whether argument use_A is True
        self.instance = A() if use_A else B()

    def do_something(self):
        # delegate to A or B instance:
        self.instance.do_something()
Run Code Online (Sandbox Code Playgroud)

更新

为了回应 Lev Barenboim 的评论,下面演示了如何使带有委托的组合看起来更像常规继承,以便如果类C已经分配了类的实例A,例如 to ,则诸如之类self.instance的属性可以也可以在内部访问(假设类本身没有定义属性),同样,如果您创建name的实例,则可以像class继承自 class一样引用它。Axself.xself.instance.xCxCcattributec.xCA

这样做的基础在于内置方法__getattr____getattribute____getattr__可以在类上定义,并且每当引用但未定义属性时都会调用。__getattribute__可以在对象上调用以按名称检索属性。

请注意,在下面的示例中,如果类所做的只是委托给 ,那么它C甚至不再需要定义方法:do_somethingself.instance

class A:
    def do_something(self):
        # some implementation

class B:
    def do_something(self):
        # some implementation

class C:
    def __init__(self, use_A):
        # assign an instance of A or B depending on whether argument use_A is True
        self.instance = A() if use_A else B()

    def do_something(self):
        # delegate to A or B instance:
        self.instance.do_something()
Run Code Online (Sandbox Code Playgroud)

印刷:

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

    def do_something(self):
        print('I am A')

class B:
    def __init__(self, x):
        self.x = x

    def do_something(self):
        print('I am B')

class C:
    def __init__(self, use_A, x):
        # assign an instance of A or B depending on whether argument use_A is True
        self.instance = A(x) if use_A else B(x)

    # called when an attribute is not found:
    def __getattr__(self, name):
        # assume it is implemented by self.instance
        return self.instance.__getattribute__(name)

    # something unique to class C:
    def foo(self):
        print ('foo called: x =', self.x)

c = C(True, 7)
print(c.x)
c.foo()
c.do_something()
# This will throw an Exception:
print(c.y)
Run Code Online (Sandbox Code Playgroud)