[更新]:回答下面的问题
我有一个检查程序,目的是让decorator中的逻辑知道它所修饰的函数是类方法还是正则函数。这以一种奇怪的方式失败了。下面是在Python2.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
执行时:
^{pr2}$有什么问题的线索吗,以及@decorate是否可以正确地推断test_call是一个方法?在
[答:] 卡尔下面的答案近乎完美。我在子类调用的方法上使用decorator时遇到了一个问题。我修改了他的代码,在超类成员中加入了im\u-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
在函数成为方法之前运行decorator。^类中的{}关键字在任何其他地方定义函数行,然后在类的主体中定义的函数作为方法添加到类中。Decorator在函数被类处理之前对其进行操作,这就是您的代码“失败”的原因。在
@decorate无法看到函数实际上是一个方法。一个解决方法是修饰函数,不管它是什么(例如,添加一个属性
do_something_about_me_if_I_am_a_method
;-)
),然后在类被计算之后再次处理它(迭代类成员并对那些修饰的成员做任何你想做的事情)。在正如其他人所说,函数在绑定之前被修饰过,所以您不能直接确定它是“方法”还是“函数”。在
判断函数是否为方法的合理方法是检查“self”是否是第一个参数。虽然不是万无一失,但大多数Python代码都遵循以下约定:
这里有一个复杂的方法,似乎可以自动地判断出方法是否是一个边界。适用于cpython2.6上的一些简单案例,但没有承诺。如果函数的第一个参数是绑定了修饰函数的对象,则它决定函数是方法。在
^{pr2}$不,这是不可能的,因为绑定方法和函数之间没有内在的区别。方法就是一个简单的函数,它将调用实例作为第一个参数(使用Pythondescriptors)。在
像这样的电话:
它返回一个未绑定的方法,转换为
^{pr2}$这是一个未绑定的方法,尽管
是一个函数。这是因为函数是其
__get__
方法返回方法的描述符;当Python在查找链中看到其中一个方法时,它将调用__get__
方法,而不是继续向上延伸。在实际上,函数的“绑定方法”是在运行时确定的,而不是在定义时确定的!在
decorator只看到定义的函数,而不在
__dict__
中查找它,因此无法判断它是否在查看绑定方法。在使用修改
__getattribute__
的类修饰符可以实现这一点,但这是一种特别讨厌的黑客攻击。为什么一定要有这个功能?当然,由于您必须自己将decorator放在函数上,所以您可以向它传递一个参数,说明所述函数是否在类中定义?在相关问题 更多 >
编程相关推荐