如何检查对象是否为方法定义?

时间:2019-06-19 14:50:04

标签: python python-decorators

我想写一个装饰器,当它得到一个函数或方法时,它会做一些不同的事情。 例如,我想编写一个缓存装饰器,但是如果它是方法,我不想将self作为键的一部分。

def cached(f):
    def _internal(*args, **kwargs):
        if ismethod(f):
            key = create_key(*args[1:], **kwargs) # ignore self from args
        else: # this is a regular function
            key = create_key(*args, **kwargs)
        return actual_cache_mechanism(key, f, *args, **kwargs)
    return _internal

class A:
    @cached
    def b(self, something):
       ...

@cached
def c(something):
    ...

问题在于,当调用@cached时,由于方法和函数都是function类型,因此无法区分方法和函数。 还能做到吗?当我想到它时,我觉得实际上方法对在其中定义它们的上下文不了解...

谢谢!

2 个答案:

答案 0 :(得分:0)

这有点丑陋,但是您可以使用obj.__qualname__通过检查对象是否有句点来查看obj是否在类中定义了

if "." in obj.__qualname__":
   #obj is a member of an object, so it is a method

我不确定它是否可以很好地用于装饰器,因为要使其正常工作,就需要在类中定义该方法。

答案 1 :(得分:0)

我认为最好以良好的Python风格避免这种内省的装饰器。

您始终可以将要缓存的函数分解为仅接受必需的参数:

@cached
def func(something):
    return ...

class A:
    def b(self, something):
        self.bvalue = func(something)

对于注释中提到的情况(需要一个对象才能获得结果,但其值不会影响它,例如套接字),请参考以下问题:How to ignore a parameter in functools. lru_cache?Make @lru_cache ignore some of the function arguments < / p>