如何在 python 中包装基础 class 方法

How to wrap a base class method in python

与 python3 合作,我有以下 类

class RESTApi:
  def __init__(self):
    self.connection = # Create connection


  def hello_world(self):
    print("Hello World !!")
  ... # More methods


class BaseVM:
  def __init__(self):
    self.restapi = RESTApi()

  def _refresh_restapi_connection(self):
    self.restapi = # Reconnect

class MyClass(BaseVM):
  def __init__(self, *args):
    BaseVM.__init__(self, *args)
  
  def create_user(self, usr, pwd):
    self.restapi.create_user(usr, pwd)

MyClass 是我与现有 类 交互的地方,我可以更改 MyClass 中的代码,但不能更改另一个 类.

我遇到的问题是 REST 连接在闲置时被清除。因此,只要 'self.restapi.XYZ' 失败,我就需要执行一个调用来刷新 REST 连接 (_refresh_restapi_connection)。

而且我希望这在 try...except 中自动完成。 'create_user' 等方法不需要知道有重新连接。

因为我不能改变另一个 类,我正在尝试创建一个包装器 self.restapi 调用

类型的东西:

class RestRetry:
    '''
    Wrapper over RESTApi class instance with retries
    '''
    def __init__(self, vm):
        self._restapi = vm.restapi

    def __getattr__(self, attrb):
        return self.rest_retry(attrb)

    def rest_retry(self, attrb):
        def _retry():
            try:
                # class REST API with retries
                result = getattr(self._restapi, attrb)
            except:
                self._refresh_restapi_connection()
                return getattr(self._restapi, attrb)
            else:
                return result
        return _retry

然后MyClass会有

def __init__(self, *args):
  BaseVM.__init__(self, *args)
  self.restapi = RestRetry()

不过没用

也许我遗漏了一些非常基本的东西,或者可能试图以错误的方式解决这个问题。

这就是我最终写的。必须更改 MyClass 中的属性名称,我不想这样做,但没有它就无法正常工作

class RestRetry:
    '''
    Wrapper over RESTApi class instance with retries
    '''
    def __init__(self, vm):
        self._vm= vm

    def __getattr__(self, attrb):
        return self.rest_retry(attrb)

    def rest_retry(self, attrb):
        def _retry(*args, **kwargs):
            try:
                # class REST API with retries though
                result = getattr(self._vm.restapi, attrb)(*args, **kwargs)
            except:
                self._vm._refresh_restapi_connection()
                return getattr(self._vm.restapi, attrb)(*args, **kwargs)
            else:
                return result
        return _retry

然后在MyClass

def __init__(self):
    BaseVM.__init__(self)
    self._restapi = self.RestRetry(self)


def any_method(self):
    self._restapi.hello_world()