Python 用于在不重复代码的情况下分派到多个类似实例的包装器类

Python 用于在不重复代码的情况下分派到多个类似实例的包装器类,python,oop,inheritance,interface,dispatch,Python,Oop,Inheritance,Interface,Dispatch,我有一个基类(或接口;在下面的Logger)的多个实现,可以互换使用。每个实现都以不同的方式处理各种事件,用户可以指定要使用的记录器类型(LoggerA或LoggerB): 类记录器: def log_foo(自我,a): 引发未实现的错误 def记录条(自身、b、c): 引发未实现的错误 类记录器(记录器): def log_foo(自我,a): 印刷品(a) def记录条(自身、b、c): 通过#不记录此事件。 类记录器B(记录器): def log_foo(自我,a): 自发送到api(a

我有一个基类(或接口;在下面的
Logger
)的多个实现,可以互换使用。每个实现都以不同的方式处理各种事件,用户可以指定要使用的记录器类型(
LoggerA
LoggerB
):

类记录器:
def log_foo(自我,a):
引发未实现的错误
def记录条(自身、b、c):
引发未实现的错误
类记录器(记录器):
def log_foo(自我,a):
印刷品(a)
def记录条(自身、b、c):
通过#不记录此事件。
类记录器B(记录器):
def log_foo(自我,a):
自发送到api(a)
def记录条(自身、b、c):
自行发送给api((b,c))
定义发送到api(自身,数据):
通过
此外,应该可以选择一次使用多个记录器实例,使用与单个记录器实例相同的界面。因此,它将以以下方式使用:

logger:logger=create\u logger\u from\u config()
logger.log_foo(…)
因此,我将为多个记录器创建此插入式替换,我发现自己以以下方式重复了大量代码:

类多记录器(记录器):
定义初始化(self,记录器:列表[Logger]):
self.loggers=记录器
def log_foo(自我,a):
对于self.loggers中的记录器:
logger.log_foo(a)
def记录条(自身、b、c):
对于self.loggers中的记录器:
logger.log_条(b,c)
这个例子只包含两个方法,但实际上有很多方法重复了这个模式。我正试图想出一个解决方案,避免这种重复,并与下面的类型检查兼容。实现这一目标的好选择是什么


我考虑过通过
\uuuu getattribute\uuuu
动态调度,但这似乎非常麻烦:

类多记录器(记录器):
定义初始化(self,记录器:列表[Logger]):
self.loggers=记录器
def uu getattribute_uu(self,name):
obj=super()
如果可调用(obj):
def代理(*args,**kwargs):
尝试:
返回对象(*args,**kwargs)
除未实施错误外:
对于self.loggers中的记录器:
getattr(记录器,名称)(*args,**kwargs)
返回代理
返回obj
我还考虑过制作
记录器
a,然后在
\uuu getattr\uuuu
中发送。虽然未在中指定,例如PyCharm将其标记为类型不匹配:

来自输入导入协议
类记录器(协议):
def log_foo(self,a):。。。
def记录条(自身、b、c):。。。
类多记录器:
定义初始化(self,记录器:列表[Logger]):
self.loggers=记录器
def _ugetattr _;(self,name):
如果可调用(getattr(记录器,名称,无)):
返回self.\u make\u代理(名称)
提升属性错误(名称)
def_make_代理(自身,名称):
def代理(*args,**kwargs):
对于self.loggers中的记录器:
getattr(记录器,名称)(*args,**kwargs)
返回代理
#PyCharm(正确地)抱怨如下:
#应为“Logger”类型,改为“MultiLogger”
#但在mypy的帮助下,它仍然有效。
logger:logger=MultiLogger([LoggerA(),LoggerB()])

从枯燥的意义上讲,这不是真正的代码重复。它只是类似的代码,可能会重复编写

多记录器
的设计与其他记录器一致。理解
LoggerA
或B的人将立即理解多记录器。我认为没有理由改变它

然而,一些替代方案的想法
这仅为每个方法保存一行(至少是重复性最强的一行):

另一个更有趣的选择是伐木工人的连锁。这将使专用的
多记录器
类变得不必要:

class Logger:
    def __init__(self, next=None):
        self.next = next

class LoggerA(Logger):
    def log_foo(self, a):
        print(a)
        if self.next:
            self.next.log_foo(a)

# usage e.g.:
logger = LoggerA(LoggerB())

从枯燥的意义上讲,这不是真正的代码重复。它只是类似的代码,可能会重复编写

多记录器
的设计与其他记录器一致。理解
LoggerA
或B的人将立即理解多记录器。我认为没有理由改变它

然而,一些替代方案的想法
这仅为每个方法保存一行(至少是重复性最强的一行):

另一个更有趣的选择是伐木工人的连锁。这将使专用的
多记录器
类变得不必要:

class Logger:
    def __init__(self, next=None):
        self.next = next

class LoggerA(Logger):
    def log_foo(self, a):
        print(a)
        if self.next:
            self.next.log_foo(a)

# usage e.g.:
logger = LoggerA(LoggerB())