python 单例模式实现

本文探讨了三种Python单例模式的实现方式:重写__new__方法、装饰器和元类,并特别关注了如何在多线程环境下确保线程安全。通过实例展示了SingletonOne、SingletonTwo和SingletonLock类的使用及其线程锁机制。
摘要由CSDN通过智能技术生成

一、重写 new 方法

# -*- coding: utf-8 -*-
# Python 单例模式实现
import pysnooper
import threading


# 方式一, 重写__new__ 方法
class SingletonOne(object):
    _instance = None

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

        return cls._instance

    def __init__(self):
        pass


class SingletonTwo(object):
    _instance = {}

    # @pysnooper.snoop()
    def __new__(cls, *args, **kwargs):
        key = str(args) + str(kwargs)
        print('key:', key)
        if key not in cls._instance:
            cls._instance[key] = super().__new__(cls)
        return cls._instance[key]

    def __init__(self, name):
        self.name = name


# 多线程
class SingletonLock(object):
    _instance = {}
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        key = str(args) + str(kwargs)
        if key in cls._instance:
            return cls._instance[key]

        cls._instance_lock.acquire()  # 获取锁对象
        try:
            if key in cls._instance:
                return cls._instance[key]
            cls._instance[key] = super().__new__(cls)
            return cls._instance[key]
        finally:
            cls._instance_lock.release()  # 释放锁对象

    def __init__(self, name):
        self.name = name


def task(name):
    obj = SingletonLock(name)
    print(obj, 'id: ', id(obj))


if __name__ == "__main__":
    s1 = SingletonOne()
    s2 = SingletonOne()
    print('SingletonOne:', id(s1) == id(s2))
    s3 = SingletonTwo('ma')
    s4 = SingletonTwo('ma')
    print('SingletonTwo:', id(s3) == id(s4))

    # 多线程调用
    for i in range(10):
        t = threading.Thread(target=task, args=['ma', ])
        t.start()

    # 正常调用
    c1 = SingletonLock('ma')
    c2 = SingletonLock('ma')
    print('SingletonLock:', id(c1) == id(c2))

二、装饰器方式

# 方式二, 装饰器
def singleton(cls):
    _instance = {}

    def _singleton(*args, **kwargs):
        key = str(args) + str(kwargs)
        print('key:', key)
        if key not in _instance:
            _instance[key] = cls(*args, **kwargs)
        return _instance[key]

    return _singleton


@singleton
class A(object):

    def __init__(self, x):
        self.x = x


if __name__ == "__main__":
	a1 = A(2)
    a2 = A(3)
    print('A:', id(a1) == id(a2))
    

三、元类的方式

class SingletonType(type):

    _instance = {}

    def __init__(self, *args, **kwargs):
        super(SingletonType, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):  # 这里的cls,即Foo类
        print('cls', cls)
        key = str(args) + str(kwargs)
        if key not in cls._instance:
            cls._instance[key] = cls.__new__(cls, *args, **kwargs)
        return cls._instance[key]

# 线程锁的方式
class SingletonType(type):
    _instance_lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType, cls).__call__(*args, **kwargs)
        return cls._instance


class Foo(metaclass=SingletonType):  # 指定创建Foo的type为SingletonType
    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)


obj1 = Foo('xx')
obj2 = Foo('xx')
print(id(obj1) == id(obj2))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值