Python之单例对象的应用

今天来讲一下单例对象的使用。

单例对象模式

 单例对象模式是一种常用的软件设计模式,这种模式保证了某一个类只能有一个实例化的对象存在。当我们希望在整个程序中某个类只能有一个实例时,就可以用到这个单例模式。

单例模式的实现方法

使用__new__方法

使用__new__方法可以限制类只能被实例化一次,直接就用下面的方法来定义就行了

class Singleton(object):
    _instance = None

    def __new__(cls,*args,**kwargs):
        if not cls._instance:
            cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)

        return cls._instance

当我们在第一次对这个类实例化一个对象的时候,类变量_instnce就会被赋值为新的对象,而再次实例化的时候cls._instance是有值的,就不会重新实例化一个新的对象。我们可以通过id来判定一下效果

a = Singleton()
b = Singleton()

print(id(a))
print(id(b))

########输出########
139968970404024
139968970404024

也就是说分别实例化的a和b其实是一个对象。

使用模块

Python的模块导入就是天然的单例模式,因为模块在第一次导入的时候就会生成一个.pyc文件,当第二次导入的 时候,就会先从pyc文件中找是否倒入过,如果以前导入过这个模块,就不再执行导入的过程。所以我们把需要的对象在模块中实例化以后导入给需要的脚本中,就是单例对象。
我们现在有个脚本文件里面定义了一个类,并且对这个类做了一个实例化

#mysingleton.py
class Animal(object):
    def run(self):
        print('running...')


a = Animal()

那么在另一个脚本中,我们把这个实例化后的对象导入一下

#main.py
from mysingleton import a

a.run()

因为这个对象a只能被导入一次,如果一个程序是由很多的脚本文件组成的,只要有一个文件导入了这个对象a,那么这个a不管在哪个脚本中被导入其实都是一个对象,即便是换了一个名称

#main.py
from mysingleton import a as a1

print('a1',id(a1))

from mysingleton import a as a2

print('a2',id(a2))

##########输出##########
a1 140212539471856
a2 140212539471856

或者是有多个py脚本

#mysingleton.py
class Animal(object):
    def run(self):
        print('running...')


a = Animal()

有一个文件调用了这个变量a

#funcs.py
from mysingleton import a

def fun():
    print('in fun a:',id(a))

还有一个文件导入了这个fun

#main.py
from mysingleton import a
import funcs
funcs.fun()
print('in main a',id(a))

最后运行的结论会是什么样的呢?

##########输出##########
in fun a: 139630131360320
in main a 139630131360320

所以这两个脚本里导入 的一个对象就是单例对象。但是要注意的是我们导入的是一个实例化以后的对象,如果仅仅是导入类以后再在脚本中实例化那么就不是单例变量了

#main.py
from mysingleton import Animal
a = Animal()
b = Animal()

print('a',id(a))
print('b',id(b))

在上面的例子中,a和b就是一般的实例化的两个对象。

使用装饰器

 这个大致看一下就行了,不作为主要的知识点

def Singleton(cls):
    _instance = {}

    def _singleton(*args,**kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args,**kwargs)
        return _instance[cls]

    return _singleton


@Singleton
class A(object):
    def fun(self):
        pass

a = A()
b = A()

print('a',id(a))
print('b',id(b))

 还有一种方式是使用metaclass元类,但是有些多线程的环境下会发生一些问题,我们这里就先不讲了。

原文地址:https://www.cnblogs.com/yinsedeyinse/p/13254379.html