【问题标题】:Python Class DecoratorPython 类装饰器
【发布时间】:2011-04-28 08:33:56
【问题描述】:

我正在尝试使用以下代码装饰一个实际的类:

def my_decorator(cls):
    def wrap(*args, **kw):
        return object.__new__(cls)
    return wrap

@my_decorator
class TestClass(object):
    def __init__(self):
        print "__init__ should run if object.__new__ correctly returns an instance of cls"


test = TestClass() # shouldn't TestClass.__init__() be run here?

我没有收到任何错误,但我也没有看到来自TestClass.__init__() 的消息。

根据the docs for new-style classes

典型实现通过使用带有适当参数的super(currentclass, cls).__new__(cls[, ...]) 调用超类的__new__() 方法来创建类的新实例,然后在返回之前根据需要修改新创建的实例。

如果__new__() 返回一个cls 的实例,那么新实例的__init__() 方法将像__init__(self[, ...]) 一样被调用,其中self 是新实例,其余参数与传递给__new__() 的参数相同。

知道为什么__init__ 没有运行吗?

另外,我曾尝试像这样拨打__new__

return super(cls.__bases__[0], cls).__new__(cls)

但它会返回一个TypeError:

TypeError: super.__new__(TestClass): TestClass is not a subtype of super

【问题讨论】:

    标签: python decorator


    【解决方案1】:

    无法告诉你原因,但这个 hack 确实运行 __init__

    def my_decorator(cls):
        print "In my_decorator()"
        def wrap(*args, **kw):
            print "In wrap()"
            return cls.__init__(object.__new__(cls), *args, **kw)
        return wrap
    
    @my_decorator
    class TestClass(object):
        def __init__(self):
            print "__init__ should run if object.__new__ correctly returns an instance of cls"
    

    【讨论】:

      【解决方案2】:

      __init__ 没有运行,因为object.__new__ 不知道调用它。如果您将其更改为 cls.__call__(*args, **kwargs),或者更好,cls(*args, **kwargs),它应该可以工作。请记住,类是可调用的:调用它会产生一个新实例。只是调用__new__ 会返回一个实例,但不会进行初始化。另一种方法是调用__new__,然后手动调用__init__,但这只是替换__call__ 中已经包含的逻辑。

      您引用的文档是指从类的__new__ 方法调用super。在这里,您是从外部调用它,而不是像我已经讨论过的那样以通常的方式调用它。

      【讨论】:

      • 出于某种原因,我认为创建实例的行为会触发__init__。感谢您的澄清!
      猜你喜欢
      • 2014-02-16
      • 2015-08-21
      • 1970-01-01
      • 2021-07-16
      • 2010-12-19
      • 2019-09-20
      • 2011-11-21
      • 2010-10-14
      相关资源
      最近更新 更多