Python多重继承:动态进行有什么问题?
根据这个回答,关于Python中__new__
和__init__
的工作原理,
我写了这段代码来动态定义和创建一个新的类和对象。
class A(object):
def __new__(cls):
class C(cls, B):
pass
self = C()
return self
def foo(self):
print 'foo'
class B(object):
def bar(self):
print 'bar'
a = A()
a.foo()
a.bar()
基本上,因为A的__new__
方法返回了一个动态创建的C类,而这个C类继承了A和B,所以它应该有一个属性bar
。
但是为什么C
却没有bar
这个属性呢?
3 个回答
3
如果你的问题是“我该怎么做才能实现这个”——这样做就可以:
class A(object):
@classmethod
def get_with_B(cls):
class C(B, cls):
pass
return C()
def foo(self):
print 'foo'
class B(object):
def bar(self):
print 'bar'
a = A.get_with_B()
a.foo()
a.bar()
如果你的问题是“为什么它不工作”——那是因为你在调用 C()
时遇到了无限递归,这导致 A.__new__
被调用,然后又会再次调用 C()
,如此循环下去。
7
因为这个“问题”里其实没有真正的问题,我就直接来聊聊吧:
动态处理有什么问题呢?
其实,这样做几乎是让人看不懂的,代码的使用者(包括一个月后的你 :P)根本不容易理解。
根据我的经验(虽然不多,遗憾的是我没有20年的编程经验),如果你需要这样的解决方案,说明你的类结构设计得不好——这意味着总有更好、更易读、也不那么复杂的方法来实现这些功能。
举个例子,如果你真的想动态定义基类,使用一个工厂函数会更好,这个函数可以根据你的需求返回合适的类。
再说说这个问题的另一个方面:
动态处理有什么问题呢?
在你现在的实现中,会出现“最大递归深度超出”的错误。这是因为 A.__new__
在内部无限调用自己(因为它继承了自己和 B
)。
10: 在 A.__new__
内部,“cls”被设置为 <class '.A'>
。在构造函数中,你定义了一个类 C
,它继承自 cls
(其实就是 A
)和另一个类 B
。当实例化 C
时,它的 __new__
被调用。因为它没有定义自己的 __new__
,所以会调用基类的 __new__
。而基类恰好是 A
。
20: 跳转到 10
7
解决无限递归的问题:
class A(object):
def __new__(cls):
class C(cls, B):
pass
self = object.__new__(C)
return self
(感谢 balpha 指出实际的问题。)