python中的条件类继承

jam*_*sRH 3 python inheritance dynamic multiple-inheritance

我正在尝试在Python中动态创建类,并且对类和类继承而言相对较新。基本上,我希望我的最终对象根据不同的需求具有不同类型的历史记录。我有一个解决方案,但我觉得必须有更好的方法。我梦到了这样的事情。

class A:
    def __init__(self):
        self.history={}
    def do_something():
        pass

class B:
    def __init__(self):
        self.history=[]
    def do_something_else():
        pass

class C(A,B):
    def __init__(self, a=False, b=False):
        if a:
            A.__init__(self)
        elif b:
            B.__init__(self)

use1 = C(a=True)
use2 = C(b=True)
Run Code Online (Sandbox Code Playgroud)

Pat*_*pin 5

您可能实际上并不需要,这可能是一个XY问题,但是在您学习语言时,这些问题经常发生。您应该意识到,通常不需要像使用其他语言那样使用Python构建庞大的类层次结构。Python使用“鸭子类型”-如果类具有您要使用的方法,只需调用它即可!

另外,在__init__调用时间时,实例已经存在。您当时无法(轻松)将其更改为其他实例(尽管实际上,一切皆有可能)。

如果您确实希望能够实例化一个类并根据传递给构造函数的内容来接收本质上是完全不同的对象的实例,则简单而直接的方法是使用一个返回不同类的实例的函数。

但是,为了完整起见,您应该知道类可以定义一个__new__方法,该方法在before之前被调用__init__。此方法可以返回该类的实例,或完全不同的类的实例,或所需的任何内容。因此,例如,您可以执行以下操作:

class A(object):
    def __init__(self):
        self.history={}
    def do_something(self):
        print("Class A doing something", self.history)

class B(object):
    def __init__(self):
        self.history=[]
    def do_something_else(self):
        print("Class B doing something", self.history)

class C(object):
    def __new__(cls, a=False, b=False):
        if a:
            return A()
        elif b:
            return B()

use1 = C(a=True)
use2 = C(b=True)
use3 = C()

use1.do_something()
use2.do_something_else()

print (use3 is None)
Run Code Online (Sandbox Code Playgroud)

这适用于Python 2或3。对于3,它将返回:

Class A doing something {}
Class B doing something []
True
Run Code Online (Sandbox Code Playgroud)


Aar*_*all 3

我假设由于某种原因您无法更改 A 和 B,并且您需要两者的功能。

也许您需要的是两个不同的类:

class CAB(A, B): 
    '''uses A's __init__'''

class CBA(B, A):
    '''uses B's __init__'''

use1 = CAB()
use2 = CBA()
Run Code Online (Sandbox Code Playgroud)

目标是动态创建一个类。

我真的不建议动态创建类。您可以使用函数来执行此操作,并且可以轻松执行诸如 pickle 实例之类的操作,因为它们在模块的全局命名空间中可用:

def make_C(a=False, b=False):
    if a:
        return CAB()
    elif b:
        return CBA()
Run Code Online (Sandbox Code Playgroud)

但如果你坚持“动态创建班级”

def make_C(a=False, b=False):
    if a:
        return type('C', (A, B), {})()
    elif b:
        return type('C', (B, A), {})()
Run Code Online (Sandbox Code Playgroud)

无论哪种方式的用法都是:

use1 = make_C(a=True)
use2 = make_C(b=True)
Run Code Online (Sandbox Code Playgroud)