python单例模式来学习!!

python单例模式来学习!!

  • 单例模式
  • 实现单例模式
    • 1、 __new__方法实现(常用)
    • 2、 使用装饰器
    • 3、模块化方法
    • 4、类方法
    • 5、指定元类(meatclass)


(声明:本教程仅供本人学习使用,如有人使用该技术触犯法律与本人无关)
(如果有错误,还希望指出。共同进步)


【注】:参考学习大佬文章 【Python中的单例模式的几种实现方式的及优化】"" 这里 “”


单例模式

单例模式从字面上来理解就是“单个的”、“实例”。
就如同某一个类只有一个实例存在。
多用于某一系统中只允许出现一个实例时。

实现单例模式

1、 __new__方法实现(常用)


__new__() 是在新式类中新出现的方法
作用: 在构造方法__init__()之前进行判断的方法
在Python 中存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()调用之前,new()决定是否要使用该init()方法
原因:__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例

【没有加入线程锁】

# __new__()中的参数cls, 代表当前类,此参数在实例化时由python解释器自动识别
class SingleInstance(object):
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        # 也可以这样写
        # if not cls._instance:
        if not hasattr(cls, "_instance"):
            cls._instance = object.__new__(cls)
        return cls._instance


obj1 = SingleInstance()
obj2 = SingleInstance()

print(id(obj1))
print(id(obj2))

# result
# 1662362768
# 1662362768

【加入线程锁,同时创建多个测试】

# !/usr/bin/python
# -*- coding:utf-8 -*-

import threading


class SingleInstance(object):
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,  "_instance"):
            print(111)
            with SingleInstance._instance_lock:
                # 也可以这样写
                # if not cls._instance:
                if not hasattr(cls, "_instance"):
                    print(222)
                    cls._instance = object.__new__(cls)
        return cls._instance


def task(args):
    obj = SingleInstance()
    # print(args)
    print(id(obj))


for i in range(10):
    t = threading.Thread(target=task, args=[i, ])
    t.start()

# print_result
# 可以看出只有第一次实现了实例化,之后直接return已有的实例化
111
222
2219381373080
2219381373080
2219381373080
2219381373080
2219381373080
2219381373080
2219381373080
2219381373080
2219381373080
2219381373080


2、 使用装饰器

def single_instance(cls):
    _instance = dict()

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

    return inner

# 下面有注释掉这行的结果,用于测试正确性
@single_instance
class TestModel(object):
    def __init__(self):
        pass


for i in range(5):
    obj = TestModel()
    print(id(obj))

# 装饰器result
2573953818576
2573953818576
2573953818576
2573953818576
2573953818576

# 正常实例化result
2657022795728
2657022985272
2657022861496
2657022795728
2657022985272

3、模块化方法

方法:创建一个py文件,定义一个类,在这个模块中实例化一次,别的模块导入
# single_instance.py
class SingleInstance(object):
    def __init__(self):
        pass


single = SingleInstance()


# 别的模块使用
from single_instance import single 

4、类方法

# !/usr/bin/python
# -*- coding:utf-8 -*-


import threading


class SingleInstance(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        import time
        time.sleep(1)

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = cls(*args, **kwargs)
        return cls._instance


def task(*args):
    obj = SingleInstance.instance()
    # print(args)
    print(id(obj))


for i in range(10):
    t = threading.Thread(target=task, args=[i, ])
    t.start()


# result
2568173385320
2568173385320
2568173385320
2568173385320
2568173385320
2568173385320
2568173385320
2568173385320
2568173385320
2568173385320

5、指定元类(meatclass)

import threading


# 创建的元类(继承自type)
class SingleInstanceType(type):
    _instance_lock = threading.Lock()

    def __int__(self):
        import time
        time.sleep(1)

    # cls指的是指定元类的类
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super().__call__(cls)
        return cls._instance


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

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


def task(*args):
    print("===============================")
    print(args)
    obj = Test(args[0])
    print(id(obj))
    这里打印不出来name,不清楚原因。后续补充,或者有大佬可以教学下
    print(obj.name)


for i in range(10):
    t = threading.Thread(target=task, args=[i, ])
    t.start()

# result
===============================
(0,)
2006831340624
<class '__main__.Test'>
===============================
(1,)
2006831340624
<class '__main__.Test'>
===============================
(2,)
2006831340624
<class '__main__.Test'>
===============================
(3,)
2006831340624
<class '__main__.Test'>
===============================
(4,)
2006831340624
<class '__main__.Test'>
===============================
(5,)
2006831340624
<class '__main__.Test'>
===============================
(6,)
2006831340624
<class '__main__.Test'>
===============================
(7,)
2006831340624
<class '__main__.Test'>
===============================
(8,)
2006831340624
<class '__main__.Test'>
===============================
(9,)
2006831340624
<class '__main__.Test'>

你可能感兴趣的:(python,python)