【发布时间】:2019-11-02 08:42:11
【问题描述】:
我想编写一个装饰器,当它获取一个函数或一个方法时,它会做一些不同的事情。
例如,我想编写一个缓存装饰器,但如果它是一种方法,我不想将 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 类型。
甚至可以做到吗?当我想到它时,我觉得实际上方法不知道它们在其中被定义的上下文......
谢谢!
【问题讨论】:
-
需要知道函数和方法的区别吗?装饰者不需要知道它们的区别。无论如何,只要通过
*args。方法将传递一个类实例 (self) 作为参数。一个函数不会。无论哪种情况,装饰器都可以传递*args。 -
你可以让你的装饰器返回一个可调用的描述符(就像一个函数一样)并对产生绑定方法的查找做出反应。这种方法可以接受吗?
-
我只是想知道为什么你需要忽略
self。如果您可以在不破坏任何内容的情况下从缓存键中省略self,这意味着结果不依赖于它,并且根本不需要self。此类方法应定义为staticmethod或classmethod(问题已解决)。 -
@VPfb 这并不完全正确。例如,
self可能包含瞬态数据(如套接字),但其当前状态与未来状态没有本质区别。所以需要self,但不属于缓存键。 @davis-herring 你能详细说明一下吗?不确定我是否理解您的方法... -
@Nadav。是的,您对套接字是正确的(例如)。实际上,我自己在
lru_cache中发布了一个关于忽略此类论点的问题。然而,在这里,OP 要求一个装饰器在没有套接字(即 self)的情况下完全工作。