6

我有一些在我的 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?

我见过的另一种方法是使用 globals 模块。就像是:

from myClass1 import MyClass1
from myClass2 import MyClass2

myObj1 = MyClass1()
myObj2 = MyClass2()

使用这个:

import globals
globals.myObj1.a()

我倾向于更喜欢第一种选择。

问题 2)在 2 个解决方案之间,您有什么建议?

问题 3)第三种解决方案是将广泛的对象(例如 Logger)传递给多个类/函数,但这不是一个好的解决方案恕我直言。这里没有提到更好的解决方案吗?

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

4

3 回答 3

5

如果您想拥有一个logger只有一个实例的类,只需将其设为单独的模块即可。

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

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

from logging import log
log("A critical error occured.")
于 2012-08-22T04:27:13.563 回答
0

考虑创建以下内容:

  1. 一个州级
  2. 代理类

state 类将创建一个线程,该线程将在init .py 模块中初始化。状态类将具有将类实例传递到线程并为其保存弱引用的方法。

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

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

于 2012-08-22T04:34:40.250 回答
-1

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

即使有一些东西,比如屏幕或记录器本质上是全局的,你仍然应该明确地传递它以允许单元测试。请注意,这仅适用于旨在成为最终设计一部分的事物。如果您的记录器只是用于调试的快速破解,请随意将其设为全局。

于 2012-08-22T04:17:16.953 回答