python中单例模式的几种实现方法

  单例模式是一种程序设计的方法,我理解单例模式:某个进程在生命周期内某类只存在一个实例对象,使用场景例如logger,配置模块,数据库连接池等,单实例可以减少资源使用,保证唯一性。

使用模块实现

  最简单实现单实例:模块化,python解释器当import一个py文件时都会把该文件编码为pyc流,当再次import就直接读取pyc文件,除非py文件内容有所更改才会再次编码:建立一个singleton.py文件,在文件中实例化singleton类,这样就实现了单例。优点是简单,但不灵活。

# *_* coding: utf-8 *_*

class singleton(object):
    pass

singleton = singleton()
   使用__new__,metaclass

     使用__new__这个魔术方法主要是在类初始化时进行控制。魔术方法可以理解为python代码和解释器的一种规约,python类在实例化时首先调用__new__去创建一个对象再__init__去初始化这个new出来的对象,所以__new__这个方法必须返回一个对象。当类中没有显式定义__new__方法时会调用父类中的__new__方法。所以要实现单例可以显式定义__new__方法:

# *_* coding: utf-8 *_*

class singleton(object):
    def __new__(cls, *args, **kwargs): 
        if not hasattr(cls, '_instance'):
            cls._instance = super(singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance
    def __init__(self):
        pass

#这里有个问题,如果实例化singleton采用多线程就会产生两个线程同时执行
#cls._instance = super(singleton, cls).__new__(cls, *args, **kwargs)的可能,所以针对多线程进行加锁,
#python中锁不用理会怎么造和创造者,拿起来就可以“咔擦”进行加锁.

import threading
class singleton(object):
    _instance_lock = threading.Lock() #建立一把锁
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with singleton._instance_lock: #使用锁,with内部代码同时只能一个线程执行 
                cls._instance = super(singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance    

    python中一切皆对象,无论我们定义一个str,int或者list都是实例化了一类。就算我们定义一个类它也是元类的实例。没显式定义父类的类都会继承object类,没显式定义元类的类都会继承type。当python解释器扫描到代码中的class A,就会调用该类的元类的__new__在内存中实例化元类的一个实例,我们实例化类A时就会调用元类的__call__方法。所以元类可以拦截类的创建并对类进行修改。元类实现单实例和__new__异曲同工:

# *_* coding: utf-8 *_*

class Meta(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Meta, cls).__call__(cls, *args, **kwargs)
        return cls._instance
#多线程安全模式
import threading
class Meta(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with Meta._instance_lock:
                cls.instance = super(Meta, cls).__call__(cls, *args, **kwargs)
        return cls._instance

#实现单实例的类需要继承Meta元类
#python 2
class singleton(object):
    __metaclass__ = Meta

#python 3 
class singleton(metaclass=Meta):
    pass
  使用装饰器
    类修饰器和函数修饰器都是同个功能:帮被修饰的对象打个包装再返回该对象,所以实现单实例也比较好理解
# *_* coding: utf-8 *_*
 
def dec(cls):
    _instance = {}
    def indec(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]
    return indec
#单实例实现方式,主要是在创建类时利用闭包原理把_instance封装在类外面,如下代码实例化singleton时候实际是调用indec函数
@dec
class singleton(object):
    pass

#多线程同
总结

   1.如果没有特别需求,用模块实现单实例方便又简单

   2.如果有多个类需要实现单实例可以使用修饰器

   3.如果有功能能上的特别定制需求才考虑使用__new__

   4.metaclass设计是给非一般的人使用的,一般是不用-_-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值