【问题标题】:Accessing a class functions via from a class decorator通过类装饰器访问类函数
【发布时间】:2021-12-04 00:07:22
【问题描述】:

我遇到了一个实现问题。

class A(object):
    "class a variables"
    
    @execute
    def worker(self):
        try:
            "do an ETL operation"
        except Exception as e:
            raise ETL exception
            
    def letmehandleETLerrors(self):
        pass
    
    def letmehandleDataIntegrityErros(self):
        pass
        
    def letmehandleDataQualityErrors(self):
        pass
        
    def letmehandleDataUpdateErrors(self):
        pass
    
    def letmehandleDataDisplayErrors(self):
        pass
        

我有一个类,在该类中,有一个名为 worker 的方法,它调用其他方法来进行一些数据处理。

我想要完成的是在我的应用程序中有一个集中的异常处理部分,我可以将所有异常处理和发布活动卸载到其中。我们有很多步骤和争论来验证数据,因此在所有地方进行异常处理变得乏味。因此,在一个名为 someExternalFile 的文件中,我概括地定义了我们的集中式异常处理:

class ETL_EXCEPTION(Exception):
    pass

class execute(object):
    def __init__(self,*args,**kwargs):
        pass
    
    def __call__(self,f):
        @wraps(f)
        def wrapped_f(*args):
            try:
                r = f(*args)
            except ETL_EXCEPTION as etlEX:
                " i would like to call ClassA.letmehandleETLerrors()"
                pass

所以基本上任何时候在其他类的任何地方引发异常,我希望这个装饰器路由到适当的处理程序以顺利进行后期活动。这里的问题是我试图找到一种方法来引用装饰器范围内的 f 类实例。我可以像这样获得对类的引用:

self.currentclass = f.__globals__[f.__qualname__.split('.')[0]]

但是当我执行 self.currentclass.letmehandleETLerrors 时,它说 letmehandleETLerrors 需要一个名为 self 的位置参数,因此实际上它创建了一个我正在考虑的 ClassA 的新实例。

这可能吗,或者我应该从一个类中取出这个包装器并将其定义为一个方法并将 A 类传递给它?

【问题讨论】:

  • 如果你没有在execute.__init__中做任何事情,你不妨用一个与execute.__call__做同样事情的简单函数替换execute类。
  • wrapped_f 已经获得了ClassA 类型的值,即args[0]

标签: python exception decorator wrapper


【解决方案1】:

生成的修饰函数将ClassA 类型的值作为其第一个参数,因此您可以使用它来访问leetmehandleETLerrors。鉴于 executeA 紧密相关,它也可以在类中定义:仅仅因为它并不意味着它必须被公开或用作实例方法。

class A:
    "class a variables"
    
    def _execute(f):
        @wraps(f)
        def wrapped_f(self, *args):
            try:
                r = f(self, *args)
            except ETL_EXCEPTION as etlEX:
                self.letmehandleETLerrors()

    @_execute
    def worker(self):
        try:
            "do an ETL operation"
        except Exception as e:
            raise ETL exception
            
    def letmehandleETLerrors(self):
        pass
    
    def letmehandleDataIntegrityErros(self):
        pass
        
    def letmehandleDataQualityErrors(self):
        pass
        
    def letmehandleDataUpdateErrors(self):
        pass
    
    def letmehandleDataDisplayErrors(self):
        pass

【讨论】:

  • 谢谢@chepner。我也在考虑这种模式。我会尝试您之前对 args[0] 的评论,或者只是转向您的建议。
  • 两者差别不大。我只是将execute 的定义移到类中,并假设它用于装饰A 中的实例方法(而不是任意函数)将selfargs 为方便起见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 2012-04-21
  • 2019-12-21
  • 1970-01-01
  • 2019-09-24
  • 2011-10-04
相关资源
最近更新 更多