【问题标题】:Python decorator for accessing class variable用于访问类变量的 Python 装饰器
【发布时间】:2018-10-31 17:15:59
【问题描述】:

我有一个装饰器来控制时间限制,如果函数执行超过限制,则会引发错误。

def timeout(seconds=10):
    def decorator(func):
        # a timeout decorator
    return decorator

我想建一个类,使用构造函数将时间限制传递给类。

def myClass:
    def __init__(self,time_limit):
        self.time_limit = time_limit

    @timeout(self.time_limit)
    def do_something(self):
        #do something

但这不起作用。

File "XX.py", line YY, in myClass
    @timeout(self.tlimit)
NameError: name 'self' is not defined

实现这个的正确方法是什么?

【问题讨论】:

  • 欢迎来到 SO。 “这行不通”这句话是没有用的。它没有帮助任何人,也没有描述任何问题。什么不起作用,会发生什么,您期望会发生什么?
  • 可以做类似self.do_something = timeout(time_limit)(self.do_something)的事情,假设你的装饰器工作。这会为类的每个实例添加一个函数对象。但是self 不在类体的范围内
  • @dfundako 我更新了,'不起作用'意味着问题没有运行,我发布了错误。
  • @MTANG 这不是你定义类的方式......
  • 你是说实例初始化?是的。那是在类主体中,所有代码都在类定义时执行,即在类初始化期间,在您创建任何实例之前。 self 只是函数的第一个参数。它像任何其他参数一样工作,即它在 函数被调用时创建一个局部变量

标签: python


【解决方案1】:

self.time_limit 仅在调用类实例中的方法时可用。

装饰器语句,作为方法的前缀,在类体被解析时运行。

但是,如果装饰器的内部部分始终应用于方法,则会将self 作为其第一个参数 - 在那里您可以简单地使用任何实例属性:

def timeout(**decorator_parms):
    def decorator(func):
        def wrapper(self, *args, **kwargs):
             time_limit = self.time_limit
             now = time.time()
             result = func(self, *args, **kwargs)
             # code to check timeout
             ..
             return result
        return wrapper
    return decorator

如果您的装饰器预计将在其他时间限制下工作,而不是始终使用self.limit,您可以始终传递一个字符串或其他常量对象,并使用简单的if 语句在最里面的装饰器中检查它。如果超时是某个字符串或对象,则使用实例属性,否则使用传入的值;

【讨论】:

  • 有效!谢谢。另外我想知道为什么我需要使用@timeout() 而不是@timeout 来使其工作?
  • 你需要额外的(),因为它最初被设计为一个“接受参数的装饰器”——它需要一个外部级别的函数(上面称为timeout的函数)只是为了注意的这些参数。如果你使用none,那么外层根本就不需要,当前的中介函数(def decorator(func):)可以放在外层。如果您这样做,则不再需要额外的括号。
  • 非常感谢!我对装饰器不是很熟悉。
【解决方案2】:

你也可以在构造函数中装饰一个方法:

def myClass:
    def __init__(self,time_limit):
        self.do_something = timeout(time_limit)(self.do_something)
    
    def do_something(self):
        #do something

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 2011-07-17
    • 2020-05-02
    • 2011-10-30
    • 2014-01-01
    • 2014-02-08
    • 2019-12-21
    相关资源
    最近更新 更多