繁体   English   中英

在Python 3中的多个模块中使用Singleton类

[英]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.pyOrange.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM