python 中的单利模式

使用场景:

+ Python的logger就是一个单例模式,用以日志记录

+ Windows的资源管理器是一个单例模式

+ 线程池,数据库连接池等资源池一般也用单例模式

+ 网站计数器

从这些使用场景我们可以总结下什么情况下需要单例模式:

   1. 当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
2. 当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。
  1. __new__方法实现
    class Singleton(object):
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
# 可以在这里给实力对象绑定一些固有属性
# cls.__instance.appkey = ""
return cls.__instance
  • 1.1
    class Singleton(object):
def __new__(cls, *args, **kwargs):
# 判断是否存在类属性_instance,_instance是类CCP的唯一对象,即单例
if not hasattr(Singleton, "__instance"):
cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
# cls.__instance = object.__new__(cls)
return cls.__instance

但是以上的方法在多线程中会有线程安全问题,当有多个线程同时去初始化对象时,就很可能同时判断__instance is None,从而进入初始化instance的代码中(如果有__init__方法)。所以需要用互斥锁来解决这个问题。

  1. 实现线程安全的单例模式
    import threading
try:
from synchronize import make_synchronized
except ImportError:
def make_synchronized(func):
import threading
func.__lock__ = threading.Lock() # 用装饰器实现同步锁
def synced_func(*args, **kwargs):
with func.__lock__:
return func(*args, **kwargs) return synced_func class Singleton(object):
__instance = None @make_synchronized
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance def __init__(self):
self.blog = "blog" # -------------
def worker():
e = Singleton()
print(id(e)) def meta():
e1 = Singleton()
e2 = Singleton()
e1.blog = 123
print(e1.blog)
print(e2.blog)
print(id(e1))
print(id(e2)) if __name__ == "__main__":
meta()
tasks = [threading.Thread(target=worker) for _ in range(20)]
for task in tasks:
task.start()
task.join()
  1. 使用装饰器来获取单例对象
    # 装饰器(decorator)可以动态地修改一个类或函数的功能
import functools
def singleton(cls):
__instance = {}
@functools.wraps(cls)
def getinstance(*args, **kwargs):
if cls not in __instance:
__instance[cls] = cls(*args, **kwargs)
return __instance[cls]
return getinstance @singleton
class MyClass(object):
a = 1

我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。

  1. 使用metaclass元类创建单例

    元类(metaclass)可以控制类的创建过程,它主要做三件事:

    • 拦截类的创建
    • 修改类的定义
    • 返回修改后的类
    class Singleton(type):
__instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls.__instances:)
cls.__instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls.__instances[cls]
# python2写法
# class MyClass(object):
# __metaclass__ = Singleton() # python3写法
class MyClass(metaclass=Singleton):
def __init__(self):
self.blog = "blog"

参考:

Python 中的单例模式

设计模式(Python)-单例模式

浅谈单利模式及其应用场景(Python)的更多相关文章

  1. 浅谈MVVM模式和MVP模式——Vue.js向

    浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...

  2. 设计模式浅谈----策略模式(c#及java实现)

    一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...

  3. 浅谈ThreadLocal模式

    一.前言: ThreadLocal模式,严格意义上不是一种设计模式,而是java中解决多线程数据共享问题的一个方案.ThreadLocal类是java JDK中提供的一个类,用来解决线程安全问题,并不 ...

  4. 浅谈代理模式与java中的动态代理

    代理模式的定义: 代理模式是一个使用律非常高的模式,定义如下: 为其他对象提供一种代理,以控制对这个对象的访问. 类图: 简单的静态代理: public interface IRunner{ //这是 ...

  5. iOS:个人浅谈工厂模式

    一.什么是工厂方法? 正式的解释是:在基类中定义创建对象的一个接口,让子类决定实例化哪个类.工厂方法让一个类的实例化延迟到子类中进行.工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好 ...

  6. 浅谈pageobject模式

    先来看两段代码 代码1: package com.zlshuo.selenium.nonaming.pageobject; /** * @author leshuo * @version 2014年5 ...

  7. 浅谈MVC模式

    MVC模式(三层架构模式) (Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  8. 浅谈MVC模式与MVVM模式的区别

    MVC模式: M:Model(数据模型),用于存放数据 V:View(视图),也就是用户界面 C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给V ...

  9. Swift语言精要 - 浅谈代理模式(Delegate)

    在iOS编程中,我们经常谈到代理代理,也就是delegate,那么什么是代理呢? 我们来看一下cocoa对它的描述: Delegation is Cocoa’s term for passing of ...

随机推荐

  1. 初识 ST 表

    推荐博客 : https://blog.csdn.net/BerryKanry/article/details/70177006 ST表通常用于RMQ问题中,询问某个区间的最值这类问题中 ST表的核心 ...

  2. Replacing the deprecated Java JPEG classes for Java 7

    [src: https://blog.idrsolutions.com/2012/05/replacing-the-deprecated-java-jpeg-classes-for-java-7/] ...

  3. Python思维导图(二)—— 数据类型

    ============================================== =========可点击图片, 放大查看更清晰哦!========= ===========有任何错误请及 ...

  4. Scrapy去重

    一.原生 1.模块 from scrapy.dupefilters import RFPDupeFilter 2.RFPDupeFilter方法 a.request_seen 核心:爬虫每执行一次yi ...

  5. 代码审计之CVE-2018-7600-Drupal远程代码执行漏洞-Render API

    今天学习一下Drupal的另一个漏洞,由于渲染数组不当造成的漏洞 poc: url:http://localhost/drupal-8.5.0/user/register?element_parent ...

  6. FluentData -Micro ORM with a fluent API that makes it simple to query a database

    Code samples Create and initialize a DbContextThe connection string on the DbContext class can be in ...

  7. c#数字图像处理(五)全等级直方图灰度拉伸

    灰度拉伸也属于线性点运算的一种,也可以通过上一节的程序得到.但由于它在点运算的特殊性,所以把它单独列出来进行介绍. 灰度拉伸定义 如果一幅图像的灰度值分布在全等级灰度范围内,即在0~255之间,那么它 ...

  8. 学_汇编语言_王爽版 要点采集笔记(未完待续…)

    第一章 基础知识 存储器(内存)存放CPU工作的指令和数据(CPU可以直接使用的信息在内存中存放):指令和数据都是二进制数没有任何区别,由CPU决定是数据还是指令 内存单元:存储器被分为若干个存储单元 ...

  9. 移动端ui框架

    https://blog.csdn.net/Robin_star_/article/details/81810197

  10. Shell之用户与权限

    用户与组 早期Linux系统设计为了能够实现多用户.多进程高效的利用服务器资源,在此种情况下,为了能够保证用户与用户之间的文件不被随意的访问及修改.删除等操作,用户.组的管理能在某种程序上实现管理用户 ...