Python中元类实现的Singleton能否继承ABC实现接口?
问题原因
你遇到的元类冲突是因为ABC抽象基类本身自带元类ABCMeta,当你定义的Logger同时继承了ILogger(元类为ABCMeta)、又指定了自定义元类Singleton,两个元类没有继承关系,就触发了Python的元类冲突规则。
你不需要完全放弃元类实现的单例,有两种常用的解决方案:
方案1:修改Singleton元类继承ABCMeta
让你的自定义Singleton元类继承ABCMeta,即可满足「派生类的元类是所有基类元类的子类」的要求,修改后代码如下:
from abc import ABC, abstractmethod, ABCMeta class Singleton(ABCMeta): # 此处将继承对象从type改为ABCMeta _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class ILogger(ABC): @abstractmethod def log(self,message: str) -> None: pass # 现在不会再报元类冲突错误 class Logger(ILogger, metaclass=Singleton): def log(self,message: str) -> None: print("Real Log: ",message) class FakeLogger(ILogger): def log(self,message: str) -> None: print("Fake Log: ",message) def task1(logger: ILogger): print("using logger ",id(logger)) logger.log("Task1 error 1 on log ")
该方案可以保留你原有的元类单例逻辑,同时兼容抽象基类的接口约束,修改后即可正常运行,业务侧使用Logger单例、测试侧替换为FakeLogger的需求也能正常实现。
方案2:改用__new__实现单例(无需修改元类)
如果你不想调整元类的继承逻辑,也可以用重写__new__方法的方式实现单例,完全不会触发元类冲突:
from abc import ABC, abstractmethod class ILogger(ABC): @abstractmethod def log(self,message: str) -> None: pass class Logger(ILogger): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance def log(self,message: str) -> None: print("Real Log: ",message) class FakeLogger(ILogger): def log(self,message: str) -> None: print("Fake Log: ",message) def task1(logger: ILogger): print("using logger ",id(logger)) logger.log("Task1 error 1 on log ")
内容的提问来源于stack exchange,提问作者Gonen I
相关产品推荐
相关产品推荐

