python中单例常用的几种实现方法总结


Posted in Python onOctober 13, 2018

前言

最近这两天在看自己之前写的代码,所以正好把用过的东西整理一下,单例模式,在日常的代码工作中也是经常被用到,

所以这里把之前用过的不同方式实现的单例方式整理一下

什么是单例?

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

那么单例模式有什么用途呢?举个常见的单例模式例子,我们平时使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例,因此回收站是单例模式的应用。

装饰器的方式

这种方式也是工作中经常用的一种,用起来也比较方便,代码实现如下

def Singleton(cls):
 _instance = {}

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

 return _singleton

如果我们工作的一个类需要用单例就通过类似下面的方式实现即可:

@Singleton
class A(object):

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

我个人还是挺喜欢这种方式的

类的方式实现

这里其实有一些问题就需要注意了,先看一下可能出现的错误代码

class Member(object):

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

乍一看这个类好像已经实现了单例,但是这里有一个潜在的问题,就是如果是多线程的情况,这样写就会有问题了,尤其是在当前类的初始化对象里有一些耗时操作时候

例如下面代码:

#! /usr/bin/env python3
# .-*- coding:utf-8 .-*-

import time
import threading
import random


class Member(object):
 
 def __init__(self):
  time.sleep(random.randint(1,3))

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


def task(arg):
 obj = Member.instance()
 print(obj)

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

这段代码的执行结果会出现实例化了多个对象,导致你写的单例就没起到作用

当然自然而然我们会想起加锁,通过锁来控制,所以我们将上面代码进行更改:

#! /usr/bin/env python3
# .-*- coding:utf-8 .-*-


import time
import threading
import random


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

 def __init__(self):
  i = random.randint(1, 3)
  print(i)
  time.sleep(i)

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


def task():
 obj = Member.instance()
 print(obj)

for i in range(5):
 threading.Thread(target=task,).start()

但是上面的代码还有一个问题,就是当我们已经实例化过之后每次调用instance都会去请求锁,所以这点并不好,所以我们将这部分代码再次更改:

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

这样就很好的实现一个可以多线程使用的单例

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
对python多线程与global变量详解
Nov 09 Python
Python 调用PIL库失败的解决方法
Jan 08 Python
Python3.4学习笔记之列表、数组操作示例
Mar 01 Python
Python3.5基础之NumPy模块的使用图文与实例详解
Apr 24 Python
django框架基于模板 生成 excel(xls) 文件操作示例
Jun 19 Python
Ranorex通过Python将报告发送到邮箱的方法
Jan 12 Python
python爬虫库scrapy简单使用实例详解
Feb 10 Python
python中urllib.request和requests的使用及区别详解
May 05 Python
Python 整行读取文本方法并去掉readlines换行\n操作
Sep 03 Python
Django如何实现防止XSS攻击
Oct 13 Python
Python基于callable函数检测对象是否可被调用
Oct 16 Python
PyTorch中permute的使用方法
Apr 26 Python
python中pika模块问题的深入探究
Oct 13 #Python
Pycharm无法使用已经安装Selenium的解决方法
Oct 13 #Python
解决python selenium3启动不了firefox的问题
Oct 13 #Python
selenium + python 获取table数据的示例讲解
Oct 13 #Python
Python3.4 splinter(模拟填写表单)使用方法
Oct 13 #Python
小白入门篇使用Python搭建点击率预估模型
Oct 12 #Python
Python读取txt内容写入xls格式excel中的方法
Oct 11 #Python
You might like
ecshop 订单确认中显示省市地址信息的方法
2010/03/15 PHP
php header函数的常用http头设置
2015/06/25 PHP
php注册登录系统简化版
2020/12/28 PHP
php实现简单爬虫的开发
2016/03/28 PHP
PHP加密解密类实例代码
2016/07/20 PHP
PHP使用finfo_file()函数检测上传图片类型的实现方法
2017/04/18 PHP
php实现根据身份证获取精准年龄
2020/02/26 PHP
JavaScript基本编码模式小结
2012/05/23 Javascript
jquery 实现checkbox全选,反选,全不选等功能代码(奇数)
2012/10/24 Javascript
jquery获得option的值和对option进行操作
2013/12/13 Javascript
jquery使用ajax实现微信自动回复插件
2014/04/28 Javascript
get(0).tagName获得作用标签示例代码
2014/10/08 Javascript
剖析Node.js异步编程中的回调与代码设计模式
2016/02/16 Javascript
jQuery easyUI datagrid 增加求和统计行的实现代码
2016/06/01 Javascript
Angular懒加载机制刷新后无法回退的快速解决方法
2016/08/30 Javascript
vue组件中点击按钮后修改输入框的状态实例代码
2017/04/14 Javascript
详解使用路由延迟加载 Angular 模块
2017/10/12 Javascript
JavaScript字符串转数字的5种方法及遇到的坑
2018/07/16 Javascript
vue中动态添加class类名的方法
2018/09/05 Javascript
vue动态设置img的src路径实例
2018/09/18 Javascript
如何从零开始手写Koa2框架
2019/03/22 Javascript
js的继承方法小结(prototype、call、apply)(推荐)
2019/04/17 Javascript
javascript设计模式 ? 简单工厂模式原理与应用实例分析
2020/04/09 Javascript
浅谈React中组件逻辑复用的那些事儿
2020/05/21 Javascript
基于JavaScript实现猜数字游戏代码实例
2020/07/30 Javascript
python实现的登陆Discuz!论坛通用代码分享
2014/07/11 Python
Python实现检测文件MD5值的方法示例
2018/04/11 Python
对Python Class之间函数的调用关系详解
2019/01/23 Python
简单了解python gevent 协程使用及作用
2019/07/22 Python
python 两个一样的字符串用==结果为false问题的解决
2020/03/12 Python
应届生简历中的自我评价
2014/01/13 职场文书
保卫科工作岗位职责
2014/03/01 职场文书
绿色环保口号
2014/06/12 职场文书
2014国庆节餐厅促销活动策划方案
2014/09/16 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
幼儿园春季开学通知
2015/07/16 职场文书