0

基于这个答案,如何__new__以及__init__应该如何在 Python 中工作,

我编写了这段代码来动态定义和创建一个新的类和对象。

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()

基本上,因为__new__A 返回一个动态创建的继承 A 和 B 的 C,所以它应该有一个属性bar

为什么C 没有属性bar

4

3 回答 3

7

由于问题中没有实际问题,我将按字面意思理解:

动态做有什么问题?
好吧,它实际上是不可读的,非常不透明并且对于您的代码的用户来说是不明显的(包括您在一个月内:P)。

根据我的经验(非常有限,我必须承认,不幸的是我没有 20 年的编程经验),对此类解决方案的需求表明,类结构没有很好地定义,-意味着,几乎总是有更好的,更易读且不那么神秘的方式来做这些事情。

例如,如果您真的想动态定义基类,最好使用工厂函数,它将根据您的需要返回适当的类。

另一个问题:
动态地做错了什么?
在您当前的实现中,它给了我一个“超出最大递归深度”的错误。发生这种情况,因为A.__new__无限期地从自身内部调用自身(因为它继承自自身和继承自B)。

10:内部A.__new__,“cls”设置为<class '.A'>。在构造函数中定义一个类C,它继承自cls(实际上是A)和另一个类B。在实例化C时,它__new__被调用。由于它没有定义它自己的__new__,它的基类'__new__被调用。基类恰好是A.
20:转到 10

于 2010-01-08T09:41:29.420 回答
7

解决无限递归:

class A(object):
  def __new__(cls):
    class C(cls, B):
      pass
    self = object.__new__(C)
    return self

(感谢balpha指出实际问题。)

于 2010-01-08T09:44:50.877 回答
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()等等。

于 2010-01-08T09:40:16.160 回答