我希望能在Python中实现一个转发类,该类实现了某个基类,并在其构造函数中接受另一个相同基类的实现,对于基类中的每个方法都将转发到该类。
这样做可以提供一个自定义点,为某些方法添加缓存、记录每个调用点周围的日志等功能。
手动编写这个类很简单。给定这个基类:
这是一个简单的转发实现。
仅编写代码的缺点是,有很多样板代码,并且必须为每个方法编写该代码。随着方法添加到基类中,类似的代码必须添加到转发类中;如果希望更改类在其转发方面的处理方式,则必须将其传播到所有方法中。 (例如,我们想更改类以使其接受上下文管理器,并在每个调用周围使用它。)
是否有一种简短的Pythonic方法可以在基本语言、内置模块或PyPI上的某些可靠模块中实现此目的?
期望功能:
确切的方法签名
转发的签名应与基类匹配 每个签名上没有*args,**kwargs
使用@property装饰器的方法被正确包装
____方法(如果存在)被正确包装
与直接实现相比,每个方法调用没有额外的成本
dir(instance)执行与直接实现相同的操作
好要有:
当基类不满足某些必要条件时出错信息
有意义的文档字符串
能够从生成的对象派生
使用@staticmethod装饰器的方法被转发到传入实现的类
使用@classmethod装饰器的方法被转发到传入实现的类
__init__和__new__不会被转发
可能存在额外复杂性的地方:
基类具有元类
基类有自己的多个基类
一些更奥妙的____及其语义
不真正关心:
多个基类
除@property、@staticmethod和@classmethod之外的自定义描述符装饰器
在转发类创建后修改基类
这样做可以提供一个自定义点,为某些方法添加缓存、记录每个调用点周围的日志等功能。
手动编写这个类很简单。给定这个基类:
class BaseClass(object):
def method_a(self, *args):
pass
@property
def prop_b(self):
pass
def method_c(self, a, b, **kwargs):
pass
这是一个简单的转发实现。
class ForwardBaseClass(BaseClass):
def __init__(self, underlying_implementation):
self._impl = underlying_implementation
def method_a(self, *args):
return self._impl.method_a(*args)
@property
def prop_b(self):
return self._impl.prop_b
def method_c(self, a, b, **kwargs):
return self._impl.method_c(a, b, **kwargs)
仅编写代码的缺点是,有很多样板代码,并且必须为每个方法编写该代码。随着方法添加到基类中,类似的代码必须添加到转发类中;如果希望更改类在其转发方面的处理方式,则必须将其传播到所有方法中。 (例如,我们想更改类以使其接受上下文管理器,并在每个调用周围使用它。)
是否有一种简短的Pythonic方法可以在基本语言、内置模块或PyPI上的某些可靠模块中实现此目的?
期望功能:
确切的方法签名
转发的签名应与基类匹配 每个签名上没有*args,**kwargs
使用@property装饰器的方法被正确包装
____方法(如果存在)被正确包装
与直接实现相比,每个方法调用没有额外的成本
dir(instance)执行与直接实现相同的操作
好要有:
当基类不满足某些必要条件时出错信息
有意义的文档字符串
能够从生成的对象派生
使用@staticmethod装饰器的方法被转发到传入实现的类
使用@classmethod装饰器的方法被转发到传入实现的类
__init__和__new__不会被转发
可能存在额外复杂性的地方:
基类具有元类
基类有自己的多个基类
一些更奥妙的____及其语义
不真正关心:
多个基类
除@property、@staticmethod和@classmethod之外的自定义描述符装饰器
在转发类创建后修改基类
getattr
将除了__init__
和__new__
(和其他不想要的东西)之外的所有内容转发到self._impl
。尽管如此,这可能不具备你所需的全部属性... - hiro protagonistself._impl
对象 - 这个额外的调用每次都会增加一些额外的成本。此外,使dir(instance)
能够工作的要求意味着需要一些更多的工作,这可能会影响每次调用的成本。 - skyking