Python实例管理

Python如何实现一个类只允许被实例化一次?这就要分两种情况:

在同一个脚本中实例化同一个类

1.这种有两种方法实现,一个是利用__new__方法,需要知道的是__new__方法运行的__init__方法之前,所以我们可以控制如何实例化类,甚至返回其它类的实例。

class Test(object):
    instance = None

    def __new__(cls):
        if cls.instance:
            return cls.instance
        cls.instance = object.__new__(cls)
        return cls.instance

    @classmethod
    def getInstance(cls):
        if cls.instance:
            return cls.instance
        cls.instance = cls()
        return cls.instance


if __name__ == '__main__':
    a = test()
    b = test()
    if a is b:
        print("equal")

2.通过类方法来实现,如上getInstance方法,这种就不很完美,因为其它人依然可以直接通过Test()这种方式来实例化类。不过我们也有办法

class Test(object):
    instance = None

    def __init__(self):
        raise Exception("该类不允许直接被实例化")

    @classmethod
    def getInstance(cls):
        if cls.instance:
            return cls.instance
        cls.instance = super(Test, cls).__init__(cls)
        return cls.instance


if __name__ == '__main__':
    a = Test.getInstance()

在不同一个脚本中实例化同一个类

如何保证在不同的脚本中导入某个模块,并且得到的该模块中某个类的实例是相同的了?(前提是这两上脚本之间,有一个import了另外一个)
我们直接在该模块的脚本A中实例化该类,当两个脚本(B和C)import该脚本A时也直接导入该实例。说的有点绕口,直接上代码。

脚本A

class A(object):
    pass

aInstance = A()

脚本B

import a

def testb():
    print(a.aInstance)
    return a.aInstance

脚本C

import a, b

def testc():
    d = b.testb()
    e = a.aInstance
    print(e)
    if d is e:
        print("equal")
    else:
        print("not equal")

if __name__ == '__main__':
    testc()

运行c.py文件输出:

<a.A object at 0x000000000337A390>
<a.A object at 0x000000000337A390>
equal

结果正是我们预计的。为什么了?
因为在Python中import时A脚本中的aInstance = A()会被自动执行,并且Python还有一个特性,在运行过程中当有Import模块时,它会把该模块对象放入sys.modules字典中,发现某个模块再次被Import时,它直接使用了sys.modules中已存在的对象。所以我们的aInstance = A()不会再次被执行,当然就只有一个实例了。

这种方式其实就是logging模块实例管理方式,大家可以看看logging源码

如果想再次Import某个模块也可以,就使用reload()函数: 比如在import a下面添加就可以reload(a)

需要注意的是在Python3中需要先from imp import reload导入reload模块。

不过就算reload(a),结果依然和上面一样。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页