Python实例方法&装饰

时间:2011-06-24 15:56:58

标签: python function methods metaprogramming decorator

我遇到了以下问题:

我需要编写一个装饰器,它能够检测到在方法和常规函数周围使用它的情况。

让我们考虑以下代码:

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>>

事实证明,装饰器在转换为方法之前应用于函数(并不令人惊讶)。

问题:您建议将两个应用程序与装饰器的角度区分开来?

修改 对于好奇的人 - 我需要因为酸洗而描述的区别。我真的不想详细介绍这个。

2 个答案:

答案 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中消失了,出于好的理由 - 它们没有任何用处,是一个毫无意义的概念并增加一些开销)只是围绕这些函数的临时包装器对象,每当函数作为属性访问时生成上课。

区分方法和函数的最佳方法是提供两个装饰器,让程序员决定应用哪个装饰器。或者甚至更好,消除这种奇怪的分离 - 方法是功能,没有什么特别的,你应该这样对待它们。