在模块之间共享单例

时间:2012-11-11 12:08:56

标签: python python-3.x singleton

给定两个模块,main和x,其中包含以下内容:

主:

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        cls._instance.x = 10
        return cls._instance
uvw = Singleton()

if __name__ == "__main__":
    print(id(uvw))
    uvw.x += 10
    print(uvw.x)
    import x
分别为

和x:

import main

print(id(main.uvw))
print(main.uvw.x)

我现在希望执行main会在两个实例中产生相同的ID和值20,但我得到的是:

$ python main.py
140592861777168
20
140592861207504
10

有什么方法可以确保uvw在两个地方都是同一个对象?

3 个答案:

答案 0 :(得分:6)

我认为问题是你的Singleton类以某种方式被重新加载,因此在第二个模块中丢失了它的_instance字段。


我认为这会奏效:

singleton.py

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        cls._instance.x = 10
        return cls._instance

a.py

from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)

b.py

from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)

main.py

import a
import b

答案 1 :(得分:6)

Python按名称加载每个模块一次(除非调用reload(module))。如果您运行main.py,则模块为__main__(尝试打印uvw.__class__.__module__)。当x导入main时,第一次加载名为main的模块。

如果您在第三个模块或uvw中定义了x,只要它以相同的方式导入__main__x - 它将是同一个对象。

答案 2 :(得分:1)

我发现问题是main在从命令行执行时加载了两次,一次加载__main__,第二次加载x作为main

我找到了一个非常邪恶的黑客来规避第二次加载:

sys.modules["main"] = sys.modules["__main__"]

在我的情况下,分离主模块和单例类是不利的。