在运行时确定基类

时间:2013-02-12 14:36:30

标签: python oop class

我想做这样的事情:

class A:

    def methodA(self):
        return 5

class B:
    def methodB(self):
        return 10

class X(...):

    def __init__(self, baseclass):
        if baseclass =='A' : derive X from A
        elif baseclass == 'B' : derive X from B
        else: raise Exception("Not supported baseclass %s!" % (baseclass))

    def methodX(self):
        return 42

X('A').methodA() # returns 5
X('A').methodX() # returns 42
X('A').methodB() # methodB not defined
X('B').methodB() # returns 10
X('B').methodX() # returns 42
X('A').methodA() # methodA not defined

我该如何实现?

2 个答案:

答案 0 :(得分:3)

如果要将methodX添加到现有类,可以考虑多重继承:

class A:
    def methodA(self):
        return 5

class B:
    def methodB(self):
        return 10

class X():
    @classmethod
    def new(cls, baseclass):
        if baseclass == A:
            return AX()
        elif baseclass == B:
            return BX()
        else: raise Exception("Not supported baseclass %s!" % str(baseclass))

    def methodX(self):
        return 42

class AX(A, X):
    pass

class BX(B, X):
    pass

您可以向X.new添加args和kwargs,并将它们传递给特定的构造函数。以下是您的测试结果(我在您的问题中更正了最后一项):

>>> ax = X.new(A)
>>> ax.methodA() # returns 5
5
>>> ax.methodX() # returns 42
42
>>> ax.methodB() # methodB not defined
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: AX instance has no attribute 'methodB'
>>> bx = X.new(B)
>>> bx.methodB() # returns 10
10
>>> bx.new(B).methodX() # returns 42
42
>>> bx.new(B).methodA() # methodA not defined
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: BX instance has no attribute 'methodA'

答案 1 :(得分:2)

您应该定义两个类XY,以及一个工厂方法来实例化X或Y,具体取决于参数。

通常,您尝试实施的行为有点令人困惑。当您创建实例(即X(...)所做的)时,您应该获得X的实例,并且类的实例应该具有相同的属性。这是课程存在的主要原因之一。

示例:

class A:
    def methodA(self):
        return 5

class B:
    def methodB(self):
        return 10

def x(class_name):
    name2class = {"A":A, "B":B}
    return name2class[class_name]()

for name in ["A","B","C"]:
    instance = x(name)
    print name, instance

将打印

A <__main__.A instance at 0x022C8D50>
B <__main__.B instance at 0x022C8DF0>
Traceback (most recent call last):
  File ".../14834949.py", line 21, in <module>
    instance = x(name)
  File ".../14834949.py", line 18, in x
    return name2class[class_name]()
KeyError: 'C'