如何区分装饰中的功能和方法

时间:2015-07-16 14:35:13

标签: python python-3.x

我正在尝试编写装饰器,根据它来做不同的工作,无论是装饰方法还是功能。

我试过这样的事情:

def dec(f):
    def wrapper(*v, **kv):
        if '__class__' in dir(f):
            text = "Its a method"
        else:
            text = "Its a function"
        print(text)
        return f(*v, **kv)
    return wrapper


class A:

    @dec
    def f(self):
        pass

@dec
def f():
    pass

a = A()

a.f()
f()

它返回:

Its a method
Its a method

但这不起作用,因为所有函数也都有__class__属性:)我也尝试在Af上做inspect.ismethod但Af就像函数一样被处理但在A命名空间中它返回当然是假的。如果我们已经完成了inspect.ismethod(a.f),其中aA的实例,那么它将返回True,但我迫不及待想要实例。

1 个答案:

答案 0 :(得分:1)

正如Martijn在他的评论中已经解释过的那样,在一个类语句中定义的函数不会使函数成为一个方法 - 方法对象是在查找时创建的,正如here所解释的那样 - 所以你要装饰的是并将永远(几乎在下面cf)成为一个功能。 FWIW,Python的“方法”只是围绕函数,类和(最终)实例的瘦包装。

除了函数之外你唯一可能得到的东西是classmethods和staticmethods(在这种情况下你会得到一个classmethodstaticmethod对象),即使这样,它依赖于关于装饰者的命令。

如果你想在装饰器中获取方法的当前实例(或类),你知道它将永远是第一个位置参数 - 但这可能不是很有帮助...总而言之,你必须明确地告诉装饰者它是否应该将函数视为普通函数或方法,或者用自定义描述符装饰它,在这种情况下你会知道函数是否已经被查找为方法。 ..天真的实现看起来像这样:

class MyDecorator(object):
    def __init__(self, func, instance=None):
        self.func = func
        self.instance = instance

    def __call__(self, *args, **kw):
        if self.instance:
            print "is method - instance : %s" % self.instance
            args = (self.instance,) + args
        else:
            print "is_function"

        return self.func(*args, **kw)

    def __get__(self, instance, cls):
        return type(self)(self.func, instance)