Python中的全局和单例

时间:2012-08-22 04:07:39

标签: python

我有一些在我的Python应用程序中普遍存在的类,它们应该只有一个全局实例(例如Logger,DbConnection)。 Python不支持类中的静态变量/方法,因此在这里创建单例的常用Java / C ++方法不起作用。我已经找到了在Python中实现单例的替代方法。我想要一个简单的(如果可能的话没有元编程)和干净的实现。这看起来不错:

class MyClass(object):
    def a():
        pass

singleton = MyClass()

使用单例将很简单

import myClass
myClass.singleton.a()

如果对象初始化不那么简单,可以用创建函数替换直接赋值。

我还可以在模块范围内创建一个getInstance()并始终使用它来获取myObj。

问题1)这可行吗?模块代码(myObj赋值)仅在第一次导入到其他模块时运行,并且每次在某处导入此模块时都不会创建myObj?

我看到的另一种方法是使用全局模块。类似的东西:

from myClass1 import MyClass1
from myClass2 import MyClass2

myObj1 = MyClass1()
myObj2 = MyClass2()

使用此:

import globals
globals.myObj1.a()

我倾向于选择第一种选择。

问题2)在两种解决方案之间,你推荐什么?

问题3)第三种解决方案是将诸如Logger之类的广泛对象传递给几个类/函数,但这不是一个很好的解决方案。这里没有提到更好的解决方案吗?

我知道使用全局变量和单例的缺点。但是,拥有全局状态在我的应用程序中不是一个大问题。我更喜欢具有代码清晰度且易于使用的解决方案。

3 个答案:

答案 0 :(得分:5)

如果你想拥有一个只有一个实例的logger类,只需将它作为一个单独的模块。

# In logging.py
def log(msg):
  print msg

然后从您要登录的任何脚本开始。

from logging import log
log("A critical error occured.")

答案 1 :(得分:0)

考虑创建以下内容:

  1. 州级
  2. 代理类
  3. 状态类将创建一个将在 init .py模块中初始化的线程。状态类将具有将类实例传递给线程并将weakref保存到其中的方法。

    稍后,可以使用代理类来访问线程中的类实例。如果未创建类对象,则代理将创建所需类的实例并将其保存到线程中。

    使用此模式,您可以将每个类的实例数限制为1,并确保每当应用程序的一部分正在运行时,不必重新创建需要全局重复使用的任何实例。

答案 2 :(得分:-1)

如何制作单身人士的正确答案?别。您应该明确地将引用传递给需要使用它的所有内容。您可以使用工厂函数,包装类等减少工作量。

即使存在某些内容,例如全局性的屏幕或记录器,您仍应明确传递它以允许进行单元测试。请注意,这仅适用于最终设计的一部分。如果您的记录器只是一个快速的调试,请随意将其设置为全局。