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

How to check if an object is a method definition?

我想编写一个装饰器,它在获取函数或方法时做一些不同的事情。 例如,我想编写一个缓存装饰器,但如果它是一种方法,我不想将 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类型。 那甚至可以做到吗?当我想到它时,我觉得实际上方法不知道它们在其中定义的上下文......

谢谢!

这是一种丑陋的 hack,但您可以使用 obj.__qualname__ 查看 obj 是否在 class 中定义,方法是检查它是否有句点

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

不过我不确定它是否适合装饰器,因为要使其正常工作,需要在 class.

中定义该方法

我认为以良好的 pythonic 风格的名义避免这种内省装饰器是可取的。

您始终可以提取要缓存的函数以仅接受所需的参数:

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

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

对于评论中提到的情况(需要一个对象来获取结果,但它的值不影响它,例如socket),请参考这些问题:How to ignore a parameter in functools. lru_cache? and