Python:将模块及其变量视为单例—;干净的方法?

Python:将模块及其变量视为单例—;干净的方法?,python,module,singleton,Python,Module,Singleton,我想在Python程序中实现某种单例模式。我想不用上课就做;也就是说,我想把所有的单函数相关的函数和变量放在一个模块中,并把它看作是一个实际的单体。 例如,假设它位于文件“singleton_module.py”中: #singleton_module.py #单态相关变量 foo='blah' 酒吧=‘东西’ #处理上述变量的函数 def功(某些参数): 全球足球俱乐部 如果某些参数: 条=。。。 其他: foo=。。。 然后,程序的其余部分(即其他模块)将使用此单例,如下所示: #另一个_

我想在Python程序中实现某种单例模式。我想不用上课就做;也就是说,我想把所有的单函数相关的函数和变量放在一个模块中,并把它看作是一个实际的单体。 例如,假设它位于文件“singleton_module.py”中:

#singleton_module.py
#单态相关变量
foo='blah'
酒吧=‘东西’
#处理上述变量的函数
def功(某些参数):
全球足球俱乐部
如果某些参数:
条=。。。
其他:
foo=。。。
然后,程序的其余部分(即其他模块)将使用此单例,如下所示:

#另一个_module.py
导入singleton_模块
#处理单例变量,
#这会在整个程序中改变它们
singleton_模块工作(…)
#自由访问单例变量
#(至少用于阅读)
打印singleton_module.foo
这对我来说似乎是一个非常好的主意,因为它在使用单例的模块中看起来非常干净

然而,singleton模块中所有这些乏味的“全局”语句都是丑陋的。它们出现在处理单例相关变量的每个函数中。在这个特定的示例中,这并不多,但是当您有10多个变量要跨多个函数管理时,这就不太好了

此外,如果您碰巧忘记了全局语句,这很容易出错:将创建函数的局部变量,并且不会更改模块的变量,这不是您想要的

那么,这算是干净的吗?是否有一种类似于我的方法,能够消除“全球”混乱


或者这不是一种简单的方法吗?

Alex Martelli的一个常见替代方案是将模块用作单例:

该类可以有多个实例,但它们都共享相同的状态。

与Sven的“Borg模式”建议类似,您可以将所有状态数据保留在一个类中,而不创建该类的任何实例。我相信,这种方法使用了新样式的类

该方法甚至可以适应Borg模式,但需要注意的是,修改类实例中的状态成员需要访问实例的
\uuuu class\uuu
属性(
instance.\uu class\uu.foo='z'
而不是
instance.foo='z'
,不过您也可以只执行
stateclass.foo='z'


请注意,即使在实例化之后,对类属性的修改也会反映在类的实例中。这包括添加新属性和删除现有属性,这可能会产生一些有趣的、可能有用的效果(尽管我也可以看到在某些情况下这实际上可能会导致问题)。你自己试试。

也许你可以把所有变量放在一个全局dict中,你可以直接在你的函数中使用这个dict而不用“全局”


为什么可以这样做。

用Python实现单例模式的一种方法也可以是:

如果类的实例已存在,则让singleton
\uuuu init()\uuuuuu
方法引发异常。更准确地说,类有一个成员
\u single
。如果此成员与
None
不同,则引发异常

class Singleton:
    __single = None
    def __init__( self ):
        if Singleton.__single:
            raise Singleton.__single
        Singleton.__single = self  
可以说,处理带有异常的单例实例创建也不是很干净。我们可以使用方法
handle()
隐藏实现细节,如中所示

def Handle( x = Singleton ):
    try:
        single = x()
    except Singleton, s:
        single = s
    return single 
< > >代码> HooLead()//Cux>方法非常类似于单模式的C++实现。我们可以在<代码> Stutelon 类中<代码>操作()/<代码> < /P> 返回新的
Singleton
实例或对类
Singleton
的现有唯一实例的引用

处理整个层次结构

如果
Single1
Single2
类派生自
Singleton
,则通过其中一个派生类存在
Singleton
的单个实例。可通过以下方法验证:

>>> child = S2( 'singlething' )
>>> junior = Handle( S1)
>>> junior.name()
'singlething'
建立并进一步提高清洁度:定义一个简单的类来存放您的全局字典,使其更易于引用:

class struct(dict):
    def __init__(self, **kwargs):
        dict.__init__(self, kwargs)
        self.__dict__ = self

g = struct(var1=None, var2=None)

def func():
    g.var1 = dict()
    g.var3 = 10
    g["var4"] = [1, 2]
    print(g["var3"])
    print(g.var4)

就像你在
g
中放入任何你想要的东西之前一样,现在它超级干净。

对于合法的单身人士:

class SingletonMeta(type):
    __classes = {} # protect against defining class with the same name
    def __new__(cls, cls_name, cls_ancestors, cls_dict): 
         if cls_name in cls.__classes:
             return cls.__classes[cls_name]
         type_instance = super(SingletonMeta, cls).__new__(cls, cls_name, cls_ancestors, cls_dict) # pass 'type' instead of 'cls' if you dont want SingletonMeta's attributes reflected in the class
         return type_instance() # call __init__

class Singleton:
    __metaclass__ = SingletonMeta
    # define __init__ however you want

    __call__(self, *args, *kwargs):
        print 'hi!'
要确定它确实是一个单例,请尝试实例化这个类或从它继承的任何类

singleton = Singleton() # prints "hi!"

你为什么一开始就需要单身呢。似乎90%认为自己想要/需要独生子女的人真的不想要。我曾经使用过一个类,它工作得很好,但是我想,既然我只有这个特定类的一个实例,我能不能将它变成一个单例类?好吧,既然你已经解决了单例类的一个问题,我想这个类会赢;)有人可能会说,如果你真的需要一个独生子女,那么州越少越好。如果你的
global
s太多,那可能也是设计不好的一个标志?也看:)似乎已经从那个里消失了——他从去年11月起就再也并没有出现过!8v(你是指引用同一实例的多个变量还是共享同一状态的多个实例?请澄清一下?@Jaydev我是指我所说的–共享同一状态的多个实例。
\uuuu shared\u state
字典是一个类变量,因此该类的所有实例都共享其状态。
>>> child = S2( 'singlething' )
>>> junior = Handle( S1)
>>> junior.name()
'singlething'
class struct(dict):
    def __init__(self, **kwargs):
        dict.__init__(self, kwargs)
        self.__dict__ = self

g = struct(var1=None, var2=None)

def func():
    g.var1 = dict()
    g.var3 = 10
    g["var4"] = [1, 2]
    print(g["var3"])
    print(g.var4)
class SingletonMeta(type):
    __classes = {} # protect against defining class with the same name
    def __new__(cls, cls_name, cls_ancestors, cls_dict): 
         if cls_name in cls.__classes:
             return cls.__classes[cls_name]
         type_instance = super(SingletonMeta, cls).__new__(cls, cls_name, cls_ancestors, cls_dict) # pass 'type' instead of 'cls' if you dont want SingletonMeta's attributes reflected in the class
         return type_instance() # call __init__

class Singleton:
    __metaclass__ = SingletonMeta
    # define __init__ however you want

    __call__(self, *args, *kwargs):
        print 'hi!'
singleton = Singleton() # prints "hi!"