我遇到了以下问题:
我需要编写一个装饰器,它能够检测到在方法和常规函数周围使用它的情况。
让我们考虑以下代码:
def somedecorator(fn):
print "decorating function:", fn
print "function class:", fn.__class__
return fn
@somedecorator
def regular_func():
print "I'm a regular function"
class SomeClass(object):
@somedecorator
def class_method(self):
print "I'm a class method"
输出显示:
decorating function: <function regular_func at 0x181d398>
function class: <type 'function'>
decorating function: <function class_method at 0x181d410>
function class: <type 'function'>
但写作:
print regular_func
print SomeClass.class_method
print SomeClass().class_method
产生输出:
<function regular_func at 0x181d398>
<unbound method SomeClass.class_method>
<bound method SomeClass.class_method of <__main__.SomeClass object at 0x16d9e50>>
事实证明,装饰器在转换为方法之前应用于函数(并不令人惊讶)。
问题:您建议将两个应用程序与装饰器的角度区分开来?
修改 对于好奇的人 - 我需要因为酸洗而描述的区别。我真的不想详细介绍这个。
答案 0 :(得分:2)
可能正在看堆栈?
def somedecorator(fn):
import traceback
print "decorating function:", fn
print "function class:", fn.__class__
print traceback.extract_stack()[-2][2]
return fn
如果已从模块输出“模块”调用装饰器,并从方法输出“SomeClass”调用。如果从函数内部调用也返回函数名,那么为了在两种情况之间进行辨别,你可以查找locals()和globals()以了解这些名称到底是什么:函数或类。
您怎么看?
编辑:对象可能超出范围,因此globals()和locals()的东西不起作用......
答案 1 :(得分:1)
你做不到。方法是一个函数。 Inside the class, there's just a regular function. Instancemethod描述符魔术仅在对象实例化时发生,并且描述符是对象的一部分,而不是类的一部分。 “未绑定的方法”(在Python 3中消失了,出于好的理由 - 它们没有任何用处,是一个毫无意义的概念并增加一些开销)只是围绕这些函数的临时包装器对象,每当函数作为属性访问时生成上课。
区分方法和函数的最佳方法是提供两个装饰器,让程序员决定应用哪个装饰器。或者甚至更好,消除这种奇怪的分离 - 方法是功能,没有什么特别的,你应该这样对待它们。