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

Python 如何检查对象是否是方法定义?,python,python-decorators,Python,Python Decorators,我想写一个decorator,当它得到一个函数或一个方法时,它会做一些不同的事情。 例如,我想编写一个缓存装饰器,但如果它是一个方法,我不想将self作为键的一部分 def缓存(f): def_内部(*args,**kwargs): 如果是方法(f): key=create_key(*args[1:],**kwargs)#忽略args中的self else:#这是一个常规函数 key=create_key(*args,**kwargs) 返回实际的缓存机制(键,f,*args,**kwargs)

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

def缓存(f):
def_内部(*args,**kwargs):
如果是方法(f):
key=create_key(*args[1:],**kwargs)#忽略args中的self
else:#这是一个常规函数
key=create_key(*args,**kwargs)
返回实际的缓存机制(键,f,*args,**kwargs)
内部返回
A类:
@缓存
def b(自我,某物):
...
@缓存
DEFC(某物):
...
问题是,当调用
@cached
时,它无法区分方法和函数,因为它们都属于
function
类型。 这能做到吗?在我思考的过程中,我觉得实际上方法并不知道它们在什么环境下被定义


谢谢

这是一种难看的攻击,但您可以使用
obj.\uuuu qualname\uuu
检查obj是否在类中定义,方法是检查它是否有句点

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

不过,我不确定它是否能很好地用于装饰器,因为要实现这一点,该方法需要在类中定义。

这是一种难看的黑客行为,但您可以使用
obj.\uuuu qualname\uuuu
通过检查obj是否有句点来查看它是否在类中定义

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

不过,我不确定它是否能很好地用于装饰器,因为要实现这一点,该方法需要在类中定义。

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

始终可以将要缓存的函数分解为只接受所需参数:

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

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

对于注释中提到的情况(需要一个对象来获得结果,但它的值不影响它,例如套接字),请参考这些问题:

我认为最好以良好的python风格的名义避免这种内省的装饰器

始终可以将要缓存的函数分解为只接受所需参数:

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

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

对于注释中提到的情况(需要一个对象来获得结果,但它的值不会影响它,例如套接字),请参考这些问题:

它需要知道函数和方法之间的区别吗?装潢师不需要知道两者的区别。不管发生什么,只要传递
*args
。方法将类实例(
self
)作为参数传递。一个函数将不起作用。无论哪种情况,decorator都可以传递
*args
。您可以让decorator返回一个可调用的描述符(就像函数一样),并对生成绑定方法的查找作出反应。这种方法可以接受吗?我只是想知道为什么你需要忽略
self
。如果可以在不破坏任何内容的情况下从缓存键中省略
self
,则表示结果不依赖于它,并且根本不需要
self
。这种方法应该被定义为
staticmethod
,或者可能是
classmethod
(问题解决了)。@VPfb这不完全正确。。例如,
self
可能包含瞬态数据(如套接字),但其当前状态与未来状态没有本质区别。因此需要
self
,但它不属于缓存键@davis herring你能详细说明一下吗?我不太明白你的方法…@Nadav。是的,您对套接字的看法是正确的(例如)。实际上,我自己在
lru\u cache
中发布了一个关于忽略此类参数的问题。然而这里OP要求一个装饰器完全不用它使用的套接字(即self)工作。它需要知道函数和方法之间的区别吗?装潢师不需要知道两者的区别。不管发生什么,只要传递
*args
。方法将类实例(
self
)作为参数传递。一个函数将不起作用。无论哪种情况,decorator都可以传递
*args
。您可以让decorator返回一个可调用的描述符(就像函数一样),并对生成绑定方法的查找作出反应。这种方法可以接受吗?我只是想知道为什么你需要忽略
self
。如果可以在不破坏任何内容的情况下从缓存键中省略
self
,则表示结果不依赖于它,并且根本不需要
self
。这种方法应该被定义为
staticmethod
,或者可能是
classmethod
(问题解决了)。@VPfb这不完全正确。。例如,
self
可能包含瞬态数据(如套接字),但其当前状态与未来状态没有本质区别。因此需要
self
,但它不属于缓存键@davis herring你能详细说明一下吗?我不太明白你的方法…@Nadav。是的,您对套接字的看法是正确的(例如)。实际上,我自己在
lru\u cache
中发布了一个关于忽略此类参数的问题。然而这里OP要求一个装饰器完全不用它使用的套接字(即self)工作。这有点有趣。。您可以使用module和name来检查对象的“路径”,看看它是否是一个类……这有点有趣。。您可以使用模块和名称来检查对象的“路径”,看看它是否是类。。。