Python 单例(Singleton)不完美解决方案之实例创建

Python 单例(Singleton)不完美解决方案

目前进行一个项目的重构工作,在重构过程中有这样子一个场景,要创建一个实例,该实例的资源被创建之后不会被改变,但是这些资源获取的时候需要进行发送http请求,且实例被创建的比较频繁,之前的代码都是随用随创,如果频繁创建,势必给获取所需的初始化资源的服务器增加了一定的压力,当前接口的响应速度也会下降很多,于是就考虑到对该实例只进行一次创建,之后复用改对象即可。

接下来就是本人在学习Python中对类的单例学习与实现的过程。

使用装饰器

首先我想到的是就是使用装饰器,代码如下:

def singleton(cls):  
    instances = {}  
    def _singleton(*args, **kw):  
        if cls not in instances:  
            instances[cls] = cls(*args, **kw)  
        return instances[cls]  
    return _singleton

@singleton
class TestSingleton(object):
    def __init__(self, *args):
        self.a = 2

A = TestSingleton()
A.a = 3
B = TestSingleton()
print id(A)
# 3
print id(B)
# 3
print A.a
# 46064808
print B.a
# 46064808
从原理上来说,就是把一个类的进行定义偷换,换为一个函数:该函数接收调用者传入的初始化的参数,并检查缓存中是否已经有了该类的对象,如果没有该类的实例,则创建一个放入缓存并返回实例,(有关并发安全问题不在此分析)看上去满足我们的要求,只需将该类的声明之上放上一个装饰器即可。接下来是踩坑时间:

坑: 类不能再次被继承
def singleton(cls, *args, **kw):
    instances = {}

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


@singleton
class TestSingleton(object):
    pass


class TestDrive(TestSingleton):
    pass

consult:
  File "D:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module>
    module = loadSource(a[0])
  File "D:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource
    module = imp.load_source(moduleName, fileName)
  File "C:\Users\python\Desktop\testgui\testgui.py", line 16, in <module>
    class TestDrive(TestSingleton):
TypeError: Error when calling the metaclass bases
    function() argument 1 must be code, not str

原因分析:类TestSingleton被装饰过之后,就会返回一个函数,而不是类本身,故在之后被继承的时候继承者声明的TestDrive(TestSingleton)中的TestSingleton本质上来说是一个method而非类。

该缺陷使得类不能再次被继承,在代码书写上有很大的局限性,不爽!继续探索更好的写法,使用装饰器返回函数的方法应该是不行了,那么就回到类继承上(metaclass最后分析)。

接下来先了解一下Python中一个类的实例化过程:

python中,一个类的实例化中调用到的魔法方法有:

    __new__(cls, *args, **kwargs) 
    __init__(self, *args, **kwargs)
对两个方法解释是:
__new__:被调用的class作为其第一个参数,该函数的功能任务是返回类的一个新实例。
__init__:被调用的实例作为其第一个参数,它不返回任何东西;其职责是初始化实例。
[官方解释](https://www.python.org/download/releases/2.2/descrintro/)
既然是__new__来创建新的实例,接下来的任务覆盖该方法,让其完成java单例模式中的getInstance逻辑即可,那么,代码来了。

使用类继承的方法。

class Singleton(object):
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance


class TestSingleton(Singleton):
    def __init__(self, b=None):
        self.a = b or 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值