一些注释/问题:
@retry
装饰器将应用于 make_request
方法 在类创建时,而 retry_kwargs
仅在 类的实例 创建时可用,因此前者必须在后者之前。
在这种情况下, 前者不能依赖于后者中可用的信息, ... 只要您使用装饰器语法...
The decorator syntax
@decorator
def xxx(...):
...
is just syntax sugar for
def xxx(...):
...
xxx = decorate(xxx)
这意味着,Python非常灵活,您可以通过类似以下的操作来强制执行:
class APIRequester:
def __init__(self, url, **kwargs):
self.url = url
self.retry_kwargs = kwargs
APIRequester.make_request = retry(**kwargs)(APIRequester.make_request)
def make_request(self):
pass
无法确定这个装饰器是否会对self参数产生影响。
你会有多个APIRequester实例吗?如果是这样,注意每次创建新实例时方法都将重新装饰:这样做是否合理?(我怀疑不行。)但请参见下面的编辑...
如果您没有多个实例,则可能不需要依赖在单例构造时可用的信息。
以上是一些Python通用原则。我怀疑您真的想要在这种情况下强制执行此问题。在我看来,你试图以一种它不设计的方式使用装饰器。
编辑:instancemethods
如果将构造函数中执行装饰的行替换为
self.make_request = retry(**kwargs)(self.make_request)
这样每个实例将得到其自己的函数修饰版本。这应该避免了对同一函数进行重新修饰时出现的任何问题。可能仍会有self
阻碍的问题。在这种情况下,您可以从定义中删除self
参数,并用staticmethod
来包装它:
self.make_request = retry(**kwargs)(staticmethod(self.make_request))
或者更好的做法是,使用装饰器语法在定义 make_request
时应用 staticmethod
,这也是 Guido 原本想要的方式。
这样做的话,它甚至有可能会正常工作!:-)
__init__
要设置类属性,为什么你要尝试将实例属性传递给装饰器? - user2357112make_request
中使用。 - chepnerretry
方法是 https://pypi.python.org/pypi/retrying 的一部分,我认为它需要作为装饰器来调用。 - flybonzai