python中单例模式是什么

单例模式是什么意思?

问题

有的时候 我们可能希望某一个对象只会在程序中出现一次,之后所有的调用使用同一个对象, 我们如何实现呢?

比如说 数据库的连接池,我需要初始化一次就可以了. 用一个对象就可以了.

如何实现无论执行多次的函数,或者类的构造方法,只会生成一个对象呢?

以下几种方式

第一种方式

  1. 如果是通过函数返回了一个对象,可以通过这种方式 来实现 无论函数执行多少次,都只会有一个对象生成.
from functools import update_wrapper
import redis
from config.DB import REDIS_CONFIG


def single(fn):
    """
    这个函数 只会计算一次.并且对函数的参数不敏感.
    single is not  sensitive to
    argument values, and will always return the ame value if
    called with different arguments.

    :param fn:
    :return:
    """
    name = fn.__name__

    def wrapper(*args, **kw):
        if name not in single.__dict__:
            ret = fn(*args, **kw)
            single.__dict__[name] = ret
            return ret
        else:
            return single.__dict__[name]

    return update_wrapper(wrapper, fn)




pool = redis.ConnectionPool(**REDIS_CONFIG, decode_responses=True)



@single
def get_redis_client():
    client = redis.Redis(connection_pool=pool)
    return client

if __name__ == '__main__':
    r = get_redis_client()
    r2 = get_redis_client()
    r3 = get_redis_client()

    print(id(r), id(r2), id(r3))

    print(r == r2 == r3)  # True 
    pass

第二种方式

直接用类装饰器来做

  1. 如果是类,可以通过类装饰器,来实现

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Time    : 2019/6/1 18:48
@File    : mysingle3.py
@Author  : frank.chang@shoufuyou.com
"""

from functools import update_wrapper


def singleton(cls):
    """
    类装饰器 的使用,
    这样简单的可以生成一个对象
    :param cls:
    :return:
    """
    dic = dict()

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

    # copy 源数据 docstring name 等等..
    return update_wrapper(wrapper, cls)


@singleton
class Person:
    """
    This is  Person
    """
    name = "Frank"


if __name__ == '__main__':
    p = Person()
    p2 = Person()
    p3 = Person()

    print(p, p2, p3)

    print(p == p2 == p3)
    print(id(p), id(p2), id(p3))

    pass

结果如下:

<__main__.Person object at 0x109e259e8> <__main__.Person object at 0x109e259e8> <__main__.Person object at 0x109e259e8>
True
4460796392 4460796392 4460796392

可以看出 是一个对象,id 是一样的.

第三种方式

  1. 实现 单例模式
    这种方式 算是 比较标准的单例模式, 直接实现 __new__ 方法 ,同时定义一个类变量保存这个值,如果没有第一次 先生成好,赋值给类变量,之后发布会这个 类变量即可.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Time    : 2019/5/30 11:01
@File    : redis_single.py
@Author  : frank.chang@shoufuyou.com
"""

import redis

from config.DB import REDIS_CONFIG


class RedisClient:
    """
    单例模式
    """
    _instance = None

    @classmethod
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = redis.StrictRedis(**REDIS_CONFIG, db=0)

        return cls._instance


if __name__ == '__main__':
    # redis 客户端初始化工作
    r = RedisClient()
    r2 = RedisClient()
    r3 = RedisClient()

    print(id(r), id(r2), id(r3))

    print(r == r2 == r3)

    pass
第四种方式 meta

使用元类来搞事情, 通过生成类的时候 实现call 魔术方法 来完成 类创建实例.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Time    : 2019/6/1 18:48
@File    : mysingle4.py
@Author  : frank.chang@shoufuyou.com

"""


class SingletonMeta(type):
    def __new__(cls, clsname, bases, clsdict):
        clsobj = super().__new__(cls, clsname, bases, clsdict)
        clsobj._instance = None
        return clsobj

    def __call__(self, *args, **kwargs):
        if self._instance is None:
            self._instance = super().__call__(*args, **kwargs)
        return self._instance


class Person(metaclass=SingletonMeta):
    def __init__(self, name='frank'):
        self.name = name

    def __str__(self):
        return "%s(name=%r)" % (self.__class__.__name__, self.name)


if __name__ == '__main__':
    p = Person()
    p2 = Person()
    p3 = Person()

    print(p == p2 == p3)  # True 
    print(id(p), id(p2), id(p3))
    pass

元类也可以直接在 clsdict 添加这个属性设置None, 其实是和上面是一样的.


class SingletonMeta(type):
    def __new__(cls, clsname, bases, clsdict):
        # 动态 添加类 的变量
        clsdict["_instance"] = None
        return super().__new__(cls, clsname, bases, clsdict)

    def __call__(self, *args, **kwargs):
        if self._instance is None:
            self._instance = super().__call__(*args, **kwargs)
        return self._instance

总结

简单总结如何在python 中生成 一个对象的方法.通过 装饰器,类装饰器,通过 __new__ 方法 ,元类等 来实现只生成一个对象. 当然 可能有很多的方法,根据自己的需求选一种就可以了.

分享快乐,留住感动. '2019-06-01 19:40:34' --frank

文档分享:
博客-单例模式是什么

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值