python 单例模式

Posted Chim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 单例模式相关的知识,希望对你有一定的参考价值。

研究了一下python的单利模式,简单地记录一下.

1.类和实例的创建过程

从创建类到初始化一个对象,简单地可以分为四个步骤:

(1)通过元类创建一个类,调用__new__完成类的创建(阶段A)

(2)初始化一个类,调用__init__,初始化一个类(阶段B)

(3)通过类创建一个对象,调用__new__(阶段D)

(4)初始化一个对象,调用__init__(阶段E)

图中阶段A,阶段B,阶段C是由元类完成的,在文件加载的时候,自动调用__new__和__init__,阶段E不是必须的.阶段D,阶段E是创建一个实例的过程,手动调用__new__和__init__.一般情况下,创建一个类只用实例化一个类,即调用__init__,而__new__的执行被隐藏了,主要是继承了父类的__new__方法

        说完了类和实例的创建过程之后,考虑一下单例模式应该在这四个阶段中哪个阶段控制比较合适?

(1)阶段A:

创建一个类的过程,也就是说类的创建并未完成.单例是建立实例上,实例的创建又是建立在类上面的,这个阶段类还没有创建,也就不太适合

(2)阶段B:

实例化一个类,这个阶段类也创建完成了,似乎有机会控制实例的个数

 (3)阶段D:

 类的创建和实例化完成了,开始创建一个实例,但还未完成,也可以控制实例的个数

 (4)阶段E:

 这个阶段,对象已经建立了,每一次实例化一个类时,对象已经建立了,控制不了实例的个数.

简单说,阶段A (创建类的过程)类没有建立,不宜控制实例数量.阶段E(类实例化的过程)实例已经创建,控制不了实例数量.在阶段B(实例化一个类)和阶段D(创建一个实例)比较容易控制实例的数量,也就最利于实现单例模式.

2.实现单例模式

(1)阶段B(实例化一个类)

主要是通过建立元类进行控制:

# B阶段
class Singleton_C(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super(Singleton_C, self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(Singleton_C, self).__call__(*args, **kwargs)
            return self.__instance
        else:
            return self.__instance
    
class C:
    __metaclass__ = Singleton_C
    def __init__(self):
        print \'I am C\'

a  = C() 
b  = C()
print a is b    # True

(2)阶段D(创建实例的过程)

# D阶段
class Singleton_D(object):
    \'\'\'实例存储在Sigleton_B类的字典中\'\'\'
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, \'_instance\'):
            cls._instance = super(Singleton_B, cls).__new__(cls, *args, **kwargs)
        return cls._instance
    
# 先继承其他类时, 会导致单例模式失效    
class D(Singleton_D):
    def __init__(self):
        print \'I am D\'

a = D()
b = D()
print a is b   # True

(3)阶段D(创建实例的过程)   --- 一个伪单例模式

每一次实现的对象不同,但共用变量

# D阶段
class Singleton_D1(object):
    _store = {}
    def __new__(cls, *args, **kwargs):
        obj = super(Singleton_B1, cls).__new__(cls, *args, **kwargs)
        print cls, obj, id(cls._store), id(obj._store), id(Singleton_B1._store)
        obj.__dict__ = cls._store
        return obj

# 先继承其他类时, 会导致单例模式失效    
class F(Singleton_D1):
    def __init__(self, name):
        self.name = name

f1 = F(\'python\')
f2 = F(\'singleton\')
print f1 is f2 # False

(4)装饰器

def singleton(cls):
    obj = {}
    def wrapper(*args, **kwargs):
        if cls not in obj:
            obj[cls] = cls(*args, **kwargs)
        return obj[cls]
    return wrapper

@singleton
class Foo(object):
    pass

f1 = Foo()
f2 = Foo()

print f1 is f2 # True

 

以上是关于python 单例模式的主要内容,如果未能解决你的问题,请参考以下文章

Python 单例设计模式

Python单例

一日一技:Python 下面最简单的单例模式写法

Python面向对象之单例模式

常用代码片段

常用代码片段