python中的条件类继承

时间:2015-09-16 01:38:50

标签: 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)

2 个答案:

答案 0 :(得分:5)

你可能并不真的需要它,这可能是一个XY问题,但是当你学习一门语言时,这些问题会定期发生。您应该知道,您通常不需要像使用其他语言一样使用Python构建庞大的类层次结构。 Python使用" duck typing" - 如果某个类有您想要使用的方法,请调用它!

此外,在调用__init__时,实例已存在。你不能(轻松地)在那个时候为不同的实例改变它(但实际上,任何事情都是可能的)。

如果真的希望能够实例化一个类并根据传递给构造函数的内容接收本质上完全不同的对象的实例,那么简单,直接的事情就是使用返回不同类实例的函数。

但是,为了完整起见,您应该知道类可以定义__new__方法,该方法在__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)

这适用于Python 2或3.使用3返回:

Class A doing something {}
Class B doing something []
True

答案 1 :(得分:4)

我假设由于某种原因你不能改变A和B,你需要两者的功能。

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

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

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

use1 = CAB()
use2 = CBA()
  

目标是动态创建一个类。

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

def make_C(a=False, b=False):
    if a:
        return CAB()
    elif b:
        return CBA()

但如果你坚持“动态创建课程”

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

两种用法都是:

use1 = make_C(a=True)
use2 = make_C(b=True)