【问题标题】:Why don't Python class method decorators receive the method as a bound method?为什么 Python 类方法装饰器不将方法作为绑定方法接收?
【发布时间】:2011-09-20 11:40:45
【问题描述】:

当我为类方法创建装饰器时,它总是接收类型为“函数”的方法。

但是,当我稍微玩弄一些东西时,我只能返回绑定方法:

class Test(object):
    def save(self):
        print "Save called"
    def func(self):
        print "Func called"

然后:

>>> type(Test.func)
<type 'instancemethod'>
>>> type(Test().func)
<type 'instancemethod'>

我最终想做的是创建一个类方法装饰器,它还装饰同一个类上的一些其他方法。我该怎么做呢?

【问题讨论】:

  • Test.func 不是绑定方法。

标签: python


【解决方案1】:

这是不可能的;您必须改用类装饰器或元类。装饰器语法

class Foo(object):
    @dec
    def bar(self): pass

意思

class Foo(object)
    def bar(self): pass
    bar = dec(bar)

class 定义被处理为:执行主体,然后收集定义并将它们包装在 class 对象中。即,装饰是在class 出现之前完成的。

【讨论】:

    【解决方案2】:

    这取决于发生的事情的顺序。

    如果你采取“正常”的方法。会发生以下情况:

    class Test(object):
        def save(self):
            print "Save called"
        def func(self):
            print "Func called"
    
    >>> Test.__dict__["func"]
    <function func at 0x00B43E30>
    >>> Test.func
    <unbound method Test.func>
    

    应该是一样的。这里会发生什么?好吧,看:

    >>> f = Test.__dict__["func"]
    >>> m = f.__get__(None, Test)
    >>> f, m
    (<function func at 0x00B43E30>, <unbound method Test.func>)
    

    第一个是原始函数对象,第二个是实际调用方法时创建的方法对象。

    此外,如果您有实例:

    >>> t = Test()
    >>> t.func
    <bound method Test.func of <__main__.Test object at 0x00B48AB0>>
    >>> f.__get__(t, Test)
    <bound method Test.func of <__main__.Test object at 0x00B48AB0>>
    

    所以这发生在属性访问上。

    现在回答你的问题:

    发生这种情况的原因是因为原始函数存在于类的__dict__ 中。方法对象的创建发生在访问时。

    【讨论】:

      猜你喜欢
      • 2014-02-18
      • 2021-04-12
      • 2010-12-31
      • 2016-10-14
      • 2023-04-05
      • 2011-09-18
      • 1970-01-01
      • 2018-10-03
      • 2015-08-08
      相关资源
      最近更新 更多