Python学习笔记之在Python中实现单例模式
有些时候你的项目中难免需要一些全局唯一的对象,这些对象大多是一些工具性的东西,在Python中实现单例模式并不是什么难事。以下总结几种方法:
使用类装饰器
使用装饰器实现单例类的时候,类本身并不知道自己是单例的,所以写代码的人可以不care这个,只要正常写自己的类的实现就可以,类的单例有装饰器保证。
def singleton(cls):
instancec = {}
def _wrapper(*args,**kwargs):
if cls not in instances:
instances[cls] = cls(*args,**kwargs)
return instances[cls]
return _wrapper
你会发现singleton装饰器内部使用了一个dict。当然你也可以用其他的方式,不过以下的实现是错误的:
def singleton(cls):
_instance = None #外部作用域的引用对于嵌套的内部作用域是只读的
def _wrapper(*args, **kwargs):
if _instance is None:
#解释器会抛出"UnboundLocalError: ...referenced before assignment"
_instance = cls(*args, **kwargs)
#赋值行为使解释器将"_instance"看作局部变量
return _instance
return _wrapper
使用元类(__metaclass__)和可调用对象(__call__)
Python的对象系统中一些皆对象,类也不例外,可以称之为”类型对象”,比较绕,但仔细思考也不难:类本身也是一种对象,只不过这种对象很特殊,它表示某一种类型。是对象,那必然是实例化来的,那么谁实例化后是这种类型对象呢?也就是元类。
Python中,class关键字表示定义一个类对象,此时解释器会按一定规则寻找__metaclass__,如果找到了,就调用对应的元类实现来实例化该类对象;没找到,就会调用type元类来实例化该类对象。
__call__是Python的魔术方法,Python的面向对象是”Duck type”的,意味着对象的行为可以通过实现协议来实现,可以看作是一种特殊的接口形式。某个类实现了__call__方法意味着该类的对象是可调用的,可以想像函数调用的样子。再考虑一下foo=Foo()这种实例化的形式,是不是很像啊。结合元类的概念,可以看出,Foo类是单例的,则在调用Foo()的时候每次都返回了同样的对象。而Foo作为一个类对象是单例的,意味着它的类(即生成它的元类)是实现了__call__方法的。所以可以如下实现:
class Singleton(type):
def __init__(cls, name, bases, attrs):
super(Singleton, cls).__init__(name, bases, attrs)
cls._instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None
# 以下不要使用'cls._instance = cls(*args, **kwargs)', 防止死循环,
# cls的调用行为已经被当前'__call__'协议拦截了
# 使用super(Singleton, cls).__call__来生成cls的实例
cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instance class Foo(object): #单例类
__metaclass__ = Singleton >>>a = Foo()
>>>b = Foo()
>>>a is b
>>>True
>>>a.x = 1
>>>b.x
>>>1
使用__new__
__init__不是Python对象的构造方法,__init__只负责初始化实例对象,在调用__init__方法之前,会首先调用__new__方法生成对象,可以认为__new__方法充当了构造方法的角色。所以可以在__new__中加以控制,使得某个类只生成唯一对象。具体实现时可以实现一个父类,重载__new__方法,单例类只需要继承这个父类就好。
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance class Foo(Singleton): #单例类
Python学习笔记之在Python中实现单例模式的更多相关文章
- Python学习笔记之从文件中读取数据
10-1 Python 学习笔记:在文本编辑器中新建一个文件,写几句话来总结一下你至此学到的Python 知识,其中每一行都以“In Python you can”打头.将这个文件命名为learnin ...
- Python学习笔记(十二)—Python3中pip包管理工具的安装【转】
本文转载自:https://blog.csdn.net/sinat_14849739/article/details/79101529 版权声明:本文为博主原创文章,未经博主允许不得转载. https ...
- python学习笔记1之-python简介及其环境安装
python学习笔记之-python简介及其环境安装 最近几年python之火不用多说,最近开始利用时间自学python,在学习的过程中,按照自己的思路和理解记录下学习的过程,并分享出来,如果正好你也 ...
- Python学习笔记整理(四)Python中的字符串..
字符串是一个有序的字符集合,用于存储和表现基于文本的信息. 常见的字符串常量和表达式 T1=‘’ 空字符串 T2="diege's" 双引号 T3=""&quo ...
- Python学习笔记之二——Python的运行机制,一般人肯定不会
前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:XX Python解释器简介 解释器是一种让其他程序运行起来的程 ...
- Python学习笔记1-搭建Python环境 和 Python Hello World!
一.搭建Python开发环境 1.选择开发工具 首先要寻找一个Python的开发工具,Python的开发工具有很多,有pyCharm .Eclipse.Visual studio等等 ,使用最多的还是 ...
- python学习笔记29(python中堆的使用)
堆(heap):优先队列的一种,使用优先队列能够以任意顺序增加对象,并且能在任意时间(可能在增加对象的同时)找到(也可能是移除)最小元素,比用于列表中min的方法要高效. Python中并没有独立的堆 ...
- python学习笔记26(python中__name__的使用)
在python中,每个py文件都是一个模块,也都是一个可执行文件,即包含main方法.因此,对每个py文件,可以单独运行,也可以import它给其他客户使用,这两种情况不一样. 1. 如果模块是被导入 ...
- Python学习笔记整理(三)Python中的动态类型简介
Python中只有一个赋值模型 一.缺少类型声明语句的情况 在Python中,类型是在运行过程中自动决定的,而不是通过代码声明.这意味着没有必要事声明变量.只要记住,这个概念实质上对变量,对象和它们之 ...
随机推荐
- uva 10983 Buy one, get the rest free 二分判定层次图
二分枚举租用飞机的最大花费,然后用小于等于最大花费的边构建层次图(依据时间) 构图思路: 利用二元组(x,y)表示 x天y城市 1. e天有飞机从a城市飞到b城市,能够承载x人,则添加单向边 ( ...
- POJ-2336 Ferry Loading II(简单DP)
Ferry Loading II Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3763 Accepted: 1919 Desc ...
- HDU 3045 - Picnic Cows - [斜率DP]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3045 It’s summer vocation now. After tedious milking, ...
- postgreSQL 自增需要使用序列
postgreSQL 自增需要使用序列 1.使用SERIAL CREATE TABLE users ( id SERIAL4 primary key , name character varying, ...
- 洛谷P2657 windy数 [SCOI2009] 数位dp
正解:数位dp 解题报告: 传送门! 这题一看就是个数位dp鸭,"不含前导零且相邻两个数字之差至少为2"这种的 然后就直接套板子鸭(板子戳总结,懒得放链接辣QAQ 然后就是套路 然 ...
- BZOJ4856 病毒感染 [Jsoi2016] dp
正解:区间dp+辅助dp 解题报告: 先放个传送门qwq 然后这题,又是一道看不懂题目的玩意儿:( 大概是语文太差 那就先解释下 其实只是一个点比较难明白就是它港 "假设JYY 进入i村庄并 ...
- CSS3实现背景透明,文字不透明
最近遇到一个需求,要在图片上显示带有半透明背景的文字,效果如下图所示: 看到这个需求之后,第一反应是使用CSS3中的opacity设置元素的透明度. <!DOCTYPE html> < ...
- SQL Server 学习博客分享列表(应用式学习 + 深入理解)
SQL Server 学习博客分享列表(应用式学习 + 深入理解) 转自:https://blog.csdn.net/tianjing0805/article/details/75047574 SQL ...
- Mint linux中调整屏幕亮度的方法
/********************************************************************* * Author : Samson * Date ...
- zabbix3.0 centos7 yum 安装与简单配置
参考文档https://www.zabbix.com/documentation/3.0/start zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.zab ...