[英]Using Singleton Classes in Multiple Modules in Python 3
这可能是一个愚蠢的问题,因为我刚刚了解了元类。
如果您在各自的文件中每个都有2个Singleton类,那么在两个文件中都复制Singleton
元类定义是不好的做法,例如
Apple.py
class Singleton(type):
_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 Apple(metaclass=Singleton):
pass
print(Apple() == Apple()) # True
Orange.py
class Singleton(type):
_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 Orange(metaclass=Singleton):
pass
print(Orange() == Orange()) # True
还是我们应该将Singleton元类代码移到其自己的文件Singleton.py
,并将其导入Apple.py
和Orange.py
?
还是使用包singleton-decorator
的@singleton
装饰singleton-decorator
?
实际上,使用元类定义单例是一种愚蠢的做法。 我不知道是谁最初提出了这种模式,现在已经很普遍了,这太过分了。
就是说,这只是一个简单的答案:当然,重复代码没有任何意义-少得多,因此即使您只需要更改一个参数也不会重复-它是完全相同的代码。 只需将其保存在一个文件中,然后从另一个文件中导入即可,即使您不想为此创建特定的文件。
现在,元类是Python中的一项强大功能,当人们知道发生了什么时,最好使用它。 否则,会有副作用,最常见的副作用是无法将您的类与其他具有元类的类(实际上可能是必要的)结合在一起。
也就是说,这是基于装饰器的非元类单例模式:
_register = {}
def singleton(cls):
def wrapper(*args, **kw):
if cls not in _register:
instance = cls(*args, **kw)
_register[cls] = instance
return _register[cls]
wrapper.__name__ = cls.__name__
return wrapper
...
@singleton
class Orange:
...
上面的代码按原样提供,但是如果小心使用它,则不会警告有人尝试创建具有不同参数的第二个实例。 可以更改它以不允许使用任何参数,或者在重新实例化时引发错误。
更好的是,装饰器模式可以在类声明时直接创建单例实例,这与元类不同,然后甚至不需要寄存器,因为该类将无法用于尝试产生不正确的它的第二个实例(尽管可以执行type(Orange)()
-如果您在一个项目中,这是一个可以破坏代码的环境:
def singleton(cls):
return cls()
这就对了。
@singleton
class Orange:
...
执行后,这会将“ Orange”添加到命名空间中,作为声明的“ Orange”类的一个且单独允许的实例。 或为此,只需执行以下操作:
class Orange:
...
Orange = Orange()
(当然,您甚至解决了跨模块共享代码的问题,根本不需要额外的代码)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.