首页 > 编程语言 >16.python-单例模式

16.python-单例模式

时间:2023-07-01 09:03:35浏览次数:51  
标签:__ Singleton 16 python instance 单例 def cls

python-单例模式

单例模式适用于需要共享对象的场景

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息

  1. 单例模式是一种软件设计模式,而不是专属于某种编程语言的语法;
  2. 单例模式只有一个实例存在;
  3. 单例模式有助于协调系统的整体性、统一性;
  4. 每一次执行 类名() 返回的对象,内存地址是相同

优点:

1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例

2、避免对资源的多重占用(比如写文件操作)

应用场景

  1. 资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如日志文件,应用配置。
  2. 控制资源的情况下,方便资源之间的互相通信。如线程池等。

实现1-使用__new__

class Singleton:
    __instance = None  # 类属性,用于保存唯一的实例

    def __new__(self):
        if self.__instance is None:
            self.__instance = object.__new__(self)

        return self.__instance

s1 = Singleton()
s2 = Singleton()

print(s1)
print(s2)

# 执行结果
<__main__.Singleton object at 0x105149550>
<__main__.Singleton object at 0x105149550>

多线程加锁

import threading

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

    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            with Singleton._instance_lock:
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = object.__new__(cls)  
        return Singleton._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)

实现2-元类继承

元类是一种特殊的Python类,它可以用来创建其他类。使用元类可以将一个类转换为单例模式,后面我们会介绍元类

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = object.__call__(*args, **kwargs)
        return cls._instances[cls]


class MyClass(metaclass=Singleton):
    pass

class MyClass2(metaclass=Singleton):
    pass


c1 = MyClass()
c2 = MyClass()
c3 = MyClass2()
c4 = MyClass2()

print(c1)
print(c2)
print(c3)
print(c4)
# 执行结果
<object object at 0x100cd9df0>
<object object at 0x100cd9df0>
<object object at 0x100cd9e40>
<object object at 0x100cd9e40>

多线程模式下的单例模式

# -*- coding: utf-8 -*-
import threading

def Singleton(cls):
    # print("log singleton")
    cls._instance = None
    cls._lock = threading.Lock()

    def __new__(*args, **kwargs): 
        # print(f"log new", args, kwargs)     # 实际上args中也包含cls和相关的参数
        with cls._lock:
            if not cls._instance:
                cls._instance = object.__new__(cls)
        return cls._instance

    cls.__new__ = __new__
    return cls


@Singleton
class T:
    def __init__(self, a):
        self.a = a

def task(a):
    s = T(a)
    print(s)

def helper():
    for i in range(5):
        t = threading.Thread(target=task, args=(2,))
        t.start()


if __name__ == '__main__':
    helper()


实现3-函数装饰器实现

def singleton(cls):
    instances = {}

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

    return wrapper


@singleton
class MyClass:
    pass


@singleton
class MyClass2:
    pass


c1 = MyClass()
c2 = MyClass()
c3 = MyClass2()
c4 = MyClass2()

print(c1)
print(c2)
print(c3)
print(c4)
# 执行结果
<__main__.MyClass object at 0x103419fa0>
<__main__.MyClass object at 0x103419fa0>
<__main__.MyClass2 object at 0x103419cd0>
<__main__.MyClass2 object at 0x103419cd0>

实现4-类方法

class Singleton(object):

    def __init__(self):
        pass

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

但是当使用多线程时会存在问题,按照以上方式创建的单例,无法支持多线程。

import time
import threading

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

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

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


def task(arg):
    obj = Singleton.instance()
    print(obj)
    
    
for i in range(10):
    t = threading.Thread(target=task,args=[i,])
    t.start()
    
    
time.sleep(20)
obj = Singleton.instance()
print(obj)

实现5-直接导入

class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()

将上面的代码保存在文件其他文件中,要使用时,直接在其他文件中导入此文件中的对象,这个对象即是单例模式的对象

from mysingleton import singleton

Note

单例在单线程模型下,是线程安全的,不管怎么样创建实例,都有且只有一个,而面对多线程任务时,一般的单例代码无法承担多线程任务,当有io延时操作时,会生成id不同的实例,所以如果需要实现多线程单例,那么就在创建实例时增加线程锁

标签:__,Singleton,16,python,instance,单例,def,cls
From: https://www.cnblogs.com/tian777/p/17518763.html

相关文章

  • python类与对象
    在Python中,类是一种用于创建对象的蓝图或模板。它们定义了对象的属性和方法。对象是类的实例化,它们是具体的、实际存在的实体。要定义一个类,可以使用class关键字,后面跟着类的名称。类名称通常使用首字母大写的驼峰命名法。下面是一个简单的类的示例:classPerson:def__init__(......
  • IDApython的学习
    IDApython的学习我的IDA情况:IDA7.7,idapython3.8这个可以作为文件导入和命令行内输入,我一般习惯命令行这里要注意是python不是IDC访问原数据idc.get_wide_byte(ea)//获取单字节,按整形解释idc.get_wide_word(ea)//获取双字节,按整形解释idc.get_wide_dword(ea)//获取......
  • python随笔
    一,安装模块windows环境下安装模块直接在CMD里面,运行命令:pipinstallparamiko, 删除命令,pipuninstallparamiko 用python连接linux,然后运行命令:importparamikohostname='192.168.1.112'username='root'password='123456'ssh=paramiko.SSHClient()ssh.set_miss......
  • python: more Layer Architecture and its Implementation in SQLite
    sqlite3:CREATETABLEDuStudentList( StudentId INTEGERPRIMARYKEYAUTOINCREMENT, StudentName TEXTNOTNULL, StudentNO TEXTNOTNULL, StudentBirthday DATETIME );Model:"""StudentListInfo.py学生类date2023-06-16edit:GeovinD......
  • python基本数据类型
    基本数据类型1、整型intage=182、浮点型floatsalary=1.53、字符串strname="mary"4、列表list   [ ],支持任意类型  [1,'jason',[1,2,3,4]]5、字典dic {"k":"v"} {'username':'mary','password':123}6、集合......
  • python调用cmd显示中文乱码及调用cmd命令
    os.system('dir')解决方法加上os.system('chcp65001')_____________________________________________________________#!/usr/bin/python3#-*-coding:UTF-8-*-importosos.system('chcp65001')result=os.system(r"dir")ss="......
  • python获取当前路径包含的文件并根据选择进行查看
    1、获取当前路径文件名。##(3)获取当前路径的文件名。importospath='./'#替换为你的路径dir=os.listdir(path)#dir是目录下的全部文件print("当前目录的全部文件名称为::",dir)fopen=open('file01','a+')#替换为你的路径fordindir:......
  • python + requests:请求头('Content-Type': 'multipart/form-data'),并且files和其他参数
    解释1.在使用'Content-Type':'multipart/form-data'上传文件时,你需要将文件作为请求体的一部分进行传输。而由于文件可能非常大,因此需要将文件分成多个部分进行传输。这就需要使用多部分编码(MultipartEncoding)来将文件分割成多个部分,并将每个部分与其它的表单数据一起打包到一......
  • 深入浅出 - 单例模式
    博主介绍:✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌Java知识图谱点击链接:体系化学习Java(Java面试专题)......
  • python import详解
    参考:https://zhuanlan.zhihu.com/p/156774410import绝对是我们在使用python时最常用的语句之一了,但其实关于import,需要注意的地方还真不少,如导入第三方库,导入自己写的库,导入相对路径下文件中的方法,在包内部的相对与绝对导入等导入源;有导入的顺序;有LazyLoad惰性导入方法;有已经导......