Python:将模块及其变量视为单例模式的思考——优雅实现?

2024-05-23 20:03:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在我的Python程序中实现某种单例模式。我在考虑不使用类来实现它;也就是说,我想将所有与单例相关的函数和变量放在一个模块中,并将其视为实际的单例。

例如,假设这是在文件“singleton_module.py”中:

# singleton_module.py

# Singleton-related variables
foo = 'blah'
bar = 'stuff'

# Functions that process the above variables
def work(some_parameter):
    global foo, bar
    if some_parameter:
        bar = ...
    else:
        foo = ...

然后,程序的其余部分(即其他模块)将使用这个单例,如下所示:

# another_module.py

import singleton_module

# process the singleton variables,
# which changes them across the entire program
singleton_module.work(...)

# freely access the singleton variables
# (at least for reading)
print singleton_module.foo

这对我来说似乎是个不错的主意,因为在使用单例的模块中,它看起来非常干净。

然而,singleton模块中所有这些乏味的“global”语句都很难看。它们出现在处理单例相关变量的每个函数中。在这个特定的例子中,这不算多,但是当您有10个以上的变量要跨多个函数进行管理时,这就不太好了。

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

那么,这会被认为是干净的吗?有没有一种类似于我的方法来解决“全球”混乱?

或者这根本不是我们要走的路?


Tags: 模块the函数py程序parameterfoobar
3条回答

Alex Martelli的Borg pattern是使用模块作为单例的常见替代方法:

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

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

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

如果类的实例已经存在,则让singleton__init()__方法引发异常。更准确地说,类有一个成员_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 
<^ >此{{CD5>}方法与单模式的C++实现非常类似。我们可以在Singleton类中有handle()

Singleton& Singleton::Handle() {

  if( !psingle ) {
    psingle = new Singleton;
  }
  return *psingle;
}

返回新的Singleton实例或对类Singleton的现有唯一实例的引用。

处理整个层次结构

如果Single1Single2类从Singleton派生,则存在通过其中一个派生类的Singleton的单个实例。这可以用这个来验证:

>>> child = S2( 'singlething' )
>>> junior = Handle( S1)
>>> junior.name()
'singlething'

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

# Singleton-related variables
my_globals = {'foo': 'blah', 'bar':'stuff'}

# Functions that process the above variables
def work(some_parameter):
    if some_parameter:
        my_globals['bar'] = ...
    else:
        my_globals['foo'] = ...

你这样做的原因是Python Scopes and Namespaces

相关问题 更多 >