我想写一个装饰器,当它得到一个函数或方法时,它会做一些不同的事情。
例如,我想编写一个缓存装饰器,但是如果它是方法,我不想将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
类型,因此无法区分方法和函数。
还能做到吗?当我想到它时,我觉得实际上方法对在其中定义它们的上下文不了解...
谢谢!
答案 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>