【问题标题】:Change instance attributes inside decorator更改装饰器内的实例属性
【发布时间】:2018-08-22 20:39:37
【问题描述】:

我已经搜索过这个问题,但我没有找到我正在寻找的答案。

基本上,我想将类构造函数包装在 try/except 子句中,以便它忽略构造函数内的特定类型的错误(但无论如何都会记录并打印它们)。我发现做到这一点的最好方法是用装饰器包装我的方法,因为我想在其他类中做同样的事情,但我不想继续重复相同的 try/except 子句。

但是,对象必须记住构造函数中是否发生异常(将其保存在该对象的布尔属性中),以便稍后在该对象调用特定方法时使用该信息之后。所以,我尝试在这个 sn-p 中做类似的事情:

def detectAndIgnoreErrors(fn):
    def wrappedFunc(*args, **kwargs):
        try:
            fn(*args, **kwargs)
            self.HasAnExceptionOccurredInInit = False
        except KeyError as e:
            self.HasAnExceptionOccurredInInit = True
            # Log and print exception
        except RuntimeError as e:
            self.HasAnExceptionOccurredInInit = True
            # Log and print exception

    return wrappedFunc


class Foo(FooSuperclass):

    @detectAndIgnoreErrors
    def __init__(self):
        # Do stuff that may raise exceptions
        pass

    def doStuff(self):
        if self.HasAnExceptionOccurredInInit:
            # Do stuff
            pass
        else:
            # Do other stuff
            pass

fooInstance = Foo()
fooInstance.doStuff()

这里的想法是让对象忽略构造函数中的错误,然后当调用doStuff() 方法时,对象会记住HasAnExceptionOccurredInInit 是否发生异常并相应地调整其行为。但是,解释器说 self 名称没有定义(这是有道理的,因为我试图在类范围之外访问它)。

然后,我尝试将装饰器作为类成员,然后我尝试将其作为类成员放在 Foo 的父类中,但这些替代方案都不起作用。

经过一番研究,我意识到装饰器是在定义时解决的,而不是在执行时解决的,所以self不可能这样使用,所以我不知道我该如何解决这个问题。

如果有人知道如何解决这个问题(或者可能是一个更好的解决方案而不是装饰器),将不胜感激。

【问题讨论】:

    标签: python decorator self


    【解决方案1】:

    包装函数没有名为self 的参数;如果您要假设 fn 是一种方法,则需要特别指定。

    def detectAndIgnoreErrors(fn):
        def wrappedFunc(self, *args, **kwargs):
            try:
                fn(self, *args, **kwargs)
                self.HasAnExceptionOccurredInInit = False
            except KeyError as e:
                self.HasAnExceptionOccurredInInit = True
                # Log and print exception
            except RuntimeError as e:
                self.HasAnExceptionOccurredInInit = True
                # Log and print exception
    
        return wrappedFunc
    

    【讨论】:

      猜你喜欢
      • 2019-02-01
      • 2021-12-09
      • 2018-04-28
      • 2015-07-14
      • 1970-01-01
      • 2016-12-20
      • 1970-01-01
      • 2019-07-29
      • 1970-01-01
      相关资源
      最近更新 更多