Python多重继承:动态进行有什么问题?

0 投票
3 回答
518 浏览
提问于 2025-04-15 17:47

根据这个回答,关于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 指出实际的问题。)

撰写回答