为什么Python类方法装饰器不接收方法作为绑定方法?
当我为一个类的方法创建装饰器时,它总是把这个方法当作“函数”类型来处理。
不过,当我稍微尝试一下其他东西时,我得到的却是绑定的方法:
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'>
我最终想做的是创建一个类方法的装饰器,同时也装饰同一个类里的其他方法。我该怎么做呢?
2 个回答
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__
中。方法对象是在访问时创建的。
3
这是不可能的;你需要使用类装饰器或 metaclass 来实现。装饰器的语法
class Foo(object):
@dec
def bar(self): pass
意味着
class Foo(object)
def bar(self): pass
bar = dec(bar)
在定义一个 class
时,处理的过程是:先执行类的主体,然后收集所有的定义,并把它们包裹在一个 class
对象里。也就是说,装饰是在 class
还没有被创建出来之前就完成了。