muc*_*out 5 python decorator inspection
[更新]:在下面回答问题
我有一个检查程序,一个目标是装饰器中的逻辑,以了解它正在装饰的功能是一个类方法还是常规功能.这是以一种奇怪的方式失败.下面是在Python 2.6中运行的代码:
def decorate(f):
print 'decorator thinks function is', f
return f
class Test(object):
@decorate
def test_call(self):
pass
if __name__ == '__main__':
Test().test_call()
print 'main thinks function is', Test().test_call
Run Code Online (Sandbox Code Playgroud)
然后执行:
decorator thinks function is <function test_call at 0x10041cd70>
main thinks function is <bound method Test.test_call of <__main__.Test object at 0x100425a90>>
Run Code Online (Sandbox Code Playgroud)
关于出错的任何线索,以及@decorate是否有可能正确地推断出test_call是一种方法?
[答案]卡尔的答案几乎是完美的.在子类调用的方法上使用装饰器时遇到问题.我调整了他的代码,在超类成员上包含了一个im_func比较:
ismethod = False
for item in inspect.getmro(type(args[0])):
for x in inspect.getmembers(item):
if 'im_func' in dir(x[1]):
ismethod = x[1].im_func == newf
if ismethod:
break
else:
continue
break
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,函数在绑定之前就被修饰了,所以你不能直接确定它是'方法'还是'函数'.
确定函数是否是方法的合理方法是检查"self"是否是第一个参数.虽然不是万无一失,但大多数Python代码都遵循这个惯例:
import inspect
ismethod = inspect.getargspec(method).args[0] == 'self'
Run Code Online (Sandbox Code Playgroud)
这是一种复杂的方式,似乎自动判断该方法是否是一个绑定.适用于CPython 2.6的一些简单案例,但没有承诺.如果第一个参数是一个绑定了装饰函数的对象,它决定一个函数是一个方法.
import inspect
def decorate(f):
def detect(*args, **kwargs):
try:
members = inspect.getmembers(args[0])
members = (x[1].im_func for x in members if 'im_func' in dir(x[1]))
ismethod = detect in members
except:
ismethod = False
print ismethod
return f(*args, **kwargs)
return detect
@decorate
def foo():
pass
class bar(object):
@decorate
def baz(self):
pass
foo() # prints False
bar().baz() # prints True
Run Code Online (Sandbox Code Playgroud)