Python中的单例模式

1.使用decorator

import sys
import ConfigParser
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance
@singleton
class MyClass(object):
    def __init__(self):
        pass

看起来很简单,就是判断是不是已经有实例了,如果有的话直接返回。
不过这里我想把Python中的decorator介绍下。知道设计模式的人知道有装饰器模式,它是这样被定义的:动态地给一个对象添加一些额外的职责。这个模式可以用于:认证,权限检查,记日志,检查参数,加锁,等等。PythonDecorator mode可以按照像其它编程语言如C++, Java等的样子来实现,但是Python在应用装饰概念方面的能力上远不止于此,Python提供了一个语法和一个编程特性来加强这方面的功能。Python提供的语法就是装饰器语法(decorator)。
在介绍decorator之前,还需要知道闭包这一概念。PythonPHPPerlRubyJavaScript等动态语言中,都已经实现了闭包特性,为什么这个特性那么重要呢?我们先来看看它的通俗一些的定义:
(1) OO编程范式中的对象是“整合了函数的数据对象”,那么闭包就是“整合了数据的函数对象”
(2)借用一个非常好的说法来做个总结:对象是附有行为的数据,而闭包是附有数据的行为。
下面左边的foo1只是一个普通的内嵌函数,而右边的boo则是一个闭包:

def  foo(x):

        y = x

        def  foo1 ():

                a = 1

                return a

        return  foo1

def  aoo(a, b):

        c = a

        def  boo (x):

                x = b + 1

                return x

        return boo

boo的特殊性在于引用了外部变量b,当aoo返回后,只要返回值(boo)一直存在,则对b的引用就会一直存在
这样的话,我们就理解singleton函数中的instances是全局的,所以它可以判断对象的单例性。

2.利用模块

Python中的模块在程序中只保存一份实例。所以把你要用的变量放在模块里,要用的时候import此模块就可以了。
在MyClass.py中:

class MyClass(object):
    def __init__(self):
        pass
singletonObject = MyClass()

然后在需要用到此实例的.py文件中import它。下面举个例子。
test.py中:

from MyClass import singletonObject
def test():
    print singletonObject

test1.py中:

from MyClass import singletonObject
from test import test
def test1():
    print singletonObject
if __name__ == '__main__':
    test()
    test1()

运行test1.py,得到结果:

<MyClass.MyClass object at 0x000000000214F668>
<MyClass.MyClass object at 0x000000000214F668>

看来确实是单例的。
参考资料:
[1] http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python/31887#31887
[2] http://www.ibm.com/developerworks/cn/linux/l-cn-closure/index.html
[3] http://www.cnblogs.com/tqsummer/archive/2011/01/24/1943314.html

Leave a Reply