Python 动态多重继承
我想在运行时根据我在AorB的初始化函数中传入的参数,选择继承哪个类,要么是类A,要么是类B。我已经尝试了以下代码,但方法的重载并不是我想要的那样:当我调用AorB("B").a()时,它返回的是A.a()而不是B.a()。我该如何在运行时选择继承哪个类呢?
更新:根据下面的反馈,我尝试了以下代码。现在我想在类C中继承AorB,但这还不行:
class A(object):
def a(self):
return "I'm A.a"
def b(self):
return "I'm A.b"
class B(object):
def a(self):
return "I'm B.a"
def c(self):
return "I'm B.c"
def AorB(classname, cache={}):
if not classname in cache:
Base = globals()[classname]
class AorB(Base):
def __init__(self):
print(classname)
Base.__init__(self)
cache[classname] = AorB
return cache[classname]()
class C(AorB):
def __init__(self, classname):
AorB.__init__(classname)
if __name__ == "__main__":
a = AorB("A")
print("A.a:", a.a())
print("A.b:", a.b())
b = AorB("B")
print("B.a:", b.a())
print("B.c:", b.c())
c = C("B")
print("C.a:", c.a())
print("C.c:", c.c())
结果是
Traceback (most recent call last):
File "classtest.py", line 28, in <module>
class C(AorB):
TypeError: Error when calling the metaclass bases
function() argument 1 must be code, not str
而不是:
A
('A.a:', "I'm A.a")
('A.b:', "I'm A.b")
B
('B.a:', "I'm B.a")
('B.c:', "I'm B.c")
B
('C.a:', "I'm B.a")
('C.c:', "I'm B.c")
3 个回答
0
我不太确定你具体的使用场景,但你可以试试用不同的type
来做一些类似下面的事情(这里的“某些东西”指的是一些条件):
def produce_C(kls, *args, **kwdargs):
return type('C', (globals()[kls],), {})(*args, **kwdargs)
不过这样可能会让类型系统感到困惑……(你可以考虑把类名改成C_from_A
或者C_from_B
,不过这样做可能会让人觉得麻烦)
0
你的代码有个问题(更新后): C不能从AorB继承,因为AorB是一个函数。
class C(AorB):
def __init__(self, classname):
AorB.__init__(classname)
因为你想在调用C的时候使用基类,你可以把C做成一个函数,然后让它依次调用AorB。
def C(basename):
return AorB(basename)
6
class A(object):
def a(self):
return "I'm A.a"
def b(self):
return "I'm A.b"
class B(object):
def a(self):
return "I'm B.a"
def c(self):
return "I'm B.c"
def make_AorB(Base, classname):
class AorB(Base):
def __init__(self):
print(classname)
Base.__init__(self)
return AorB
def make_C(Base, classname):
class C(Base):
def __init__(self):
Base.__init__(self)
def d(self):
return "I'm C.d"
return C
def make_factory(getbase, make_cls):
def factory(classname):
if not classname in factory.cache:
Base = getbase(classname)
factory.cache[classname] = make_cls(Base, classname)
return factory.cache[classname]()
factory.cache = {}
return factory
AorB = make_factory(lambda classname: globals()[classname], make_AorB)
C = make_factory(lambda classname: AorB.cache[classname], make_C)
if __name__ == "__main__":
a = AorB("A")
print(a.__class__, a.__class__.__bases__)
print("A.a:", a.a())
print("A.b:", a.b())
b = AorB("B")
print(b.__class__, b.__class__.__bases__)
print("B.a:", b.a())
print("B.c:", b.c())
c = C("B")
print(c.__class__, c.__class__.__bases__)
print("C.a:", c.a())
print("C.c:", c.c())
print("C.d:", c.d())
A
(<class '__main__.AorB'>, (<class '__main__.A'>,))
('A.a:', "I'm A.a")
('A.b:', "I'm A.b")
B
(<class '__main__.AorB'>, (<class '__main__.B'>,))
('B.a:', "I'm B.a")
('B.c:', "I'm B.c")
B
(<class '__main__.C'>, (<class '__main__.AorB'>,))
('C.a:', "I'm B.a")
('C.c:', "I'm B.c")
('C.d:', "I'm C.d")
产生