Python 高级编程——单例模式
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
在 Python 中,我们可以用多种方法来实现单例模式:
- 使用模块
- 使用
__new__ - 使用装饰器(decorator)
- 使用元类(metaclass)
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass my_singleton = My_Singleton() #这一步不可以少
将上面的代码保存在文件 mysingleton.py 中,然后这样使用:
from mysingleton import my_singleton
my_singleton.foo()
使用 __new__
为了使类只能出现一个实例,我们可以使用 __new__ 来控制实例的创建过程,代码如下:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kw):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance class MyClass(Singleton):
a = 1
使用装饰器:
我们知道,装饰器(decorator)可以动态地修改一个类或函数的功能。这里,我们也可以使用装饰器来装饰某个类,使其只能生成一个实例,代码如下:
from functools import wraps def singleton(cls):
instances = {}
@wraps(cls)
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance @singleton
class MyClass(object):
在上面,我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。
使用 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):
# pass
Python 高级编程——单例模式的更多相关文章
- python高级编程:有用的设计模式1
# -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...
- python高级编程读书笔记(一)
python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...
- python高级编程:有用的设计模式3
# -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#访问者:有助于将算法从数据结构中分离出来"&qu ...
- python高级编程:有用的设计模式2
# -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...
- python高级编程技巧
由python高级编程处学习 http://blog.sina.com.cn/s/blog_a89e19440101fb28.html Python列表解析语法[]和生成 器()语法类似 [expr ...
- python高级编程之选择好名称:完
由于时间关系,python高级编程不在放在这边进行学习了,如果需要的朋友可以看下面的网盘进行下载 # # -*- coding: utf-8 -*- # # python:2.x # __author ...
- python高级编程之列表推导式
1. 一个简单的例子 在Python中,如果我们想修改列表中所有元素的值,可以使用 for 循环语句来实现. 例如,将一个列表中的每个元素都替换为它的平方: >>> L = [1, ...
- Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍
原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...
- Python高级编程-Python一切皆对象
Python高级编程-Python一切皆对象 Python3高级核心技术97讲 笔记 1. Python一切皆对象 1.1 函数和类也是对象,属于Python的一等公民 ""&qu ...
随机推荐
- Servlet开发的三种方法
第一种 实现 Servlet 接口,需要覆写 Servlet 的5个方法,并将ServletConfig对象保存到类级变量中 package app01a; import java.io.IOExce ...
- Spring 中参数名称解析 - ParameterNameDiscoverer
Spring 中参数名称解析 - ParameterNameDiscoverer Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.ht ...
- Mockito学习1
Mockito学习1 junitmaven软件测试框架项目管理 Mockito是一个流行的Mocking框架.它使用起来简单,学习成本很低,而且具有非常简洁的API,测试代码的可读性很高.因此它十分 ...
- 使用yarn 安装 Vue-DevTools
1. 从 github 下载 vuejs/vue-devtools https://github.com/vuejs/vue-devtools/archive/dev.zip 2.安装yarn 及 编 ...
- mybatis学习 十六 auto_mapping实现连表查询
只能使用多表联合查询方式. 要求:查询出的列别和属性名相同. 点字符 "." 在 SQL 是关键字符,两侧添加反单引号(Tab键上的一个字符) <select id=&q ...
- java ajax请求后台并获取到返回值
js: $.ajax({ url : '../Islogin.do', type : 'get', cache : false, dataType : 'json', success : functi ...
- 统计方形(NOIP1997)
给链接:统计方形 这题是棋盘问题的数据加强版. 其实由于洛谷的数据比较水,所以你把我在棋盘问题题解中写的代码提交,也能AC. 但让给我们来看一个更优的解法. 先给代码: #include<bit ...
- 821. Shortest Distance to a Character
class Solution { public: vector<int> shortestToChar(string S, char C) { int len=S.length(); ve ...
- 2019.01.14 bzoj4530: [Bjoi2014]大融合(线段树合并)
传送门 线段树合并菜题. 题意简述:nnn个点,支持连边以及查询一个点所在连通块中经过这个点的路径条数,保证这张图时刻为森林. 思路: 先建出所有操作完之后的树统计出dfsdfsdfs序 注意有可能是 ...
- jquery特殊字符转义方法
//特殊字符转义function escapeJquery(srcString) { // 转义之后的结果 var escapseResult = srcString; // javascript正则 ...