Python 用__new__方法实现单例的操作


Posted in Python onDecember 11, 2020

介绍

init 方法通常用在初始化一个类实例时候,但其实它不是实例化一个类的时候第一个被调用 的方法。当使用 Student(id, name) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 new 方法。

new方法接受的参数虽然也是和init一样,但init是在类实例创建之后调用,而 new方法正是创建这个类实例的方法。

new为对象分配空间,是内置的静态方法,new在内存中为对象分配了空间也返回了对象的引用,init获得了这个引用才初始化这个实例。

示例

一个非常简单的单例

class A:
 instance = None
 def __new__(cls, *args, **kwargs):
  if cls.instance is None:
   cls.instance = super().__new__(cls)
  return cls.instance

因为new方法是一个静态方法(也就是在定义的时候就没有cls参数),所以在这里要传入一个cls参数,而且这里的new你改造过了,所以要返回爸爸的new方法。

按造这个方法改造的单例怎么new都是同一个实例,但init仍然会被执行多次,也就是创建了几个对象就调用几次初始化方法。所以还要对init再进行一些判断。

class A:
 instance = None
 init_flag = False # 初始化标记

 def __new__(cls, *args, **kwargs):
  if cls.instance is None:
   cls.instance = super().__new__(cls)
  return cls.instance

 def __init__(self):
  if A.init_flag:
   return
  print('执行了初始化方法')
  A.init_flag = True

if __name__ == '__main__':
 a = A()
 b = A()
 print(a)
 print(b)

输出结果:

执行了初始化方法

<main.A object at 0x00000210E6F09320>

<main.A object at 0x00000210E6F09320>

总结

通过重载new方法,可以比较简单地实现单例,Python还有很多有趣的内置函数,有空可以再研究研究。

补充知识:Python饿汉式和懒汉式单例模式的实现

看代码吧~

# 饿汉式
class Singleton(object):
 # 重写创建实例的__new__方法
 def __new__(cls):
  # 如果类没有实例属性,进行实例化,否则返回实例
  if not hasattr(cls, 'instance'):
   cls.instance = super(Singleton, cls).__new__(cls)
  return cls.instance

饿汉式在创建的时候就会生成实例

# 懒汉式
class Singleton(object):
 __instance = None
 def __init__(self):
  if not self.__instance:
   print('调用__init__, 实例未创建')
  else:
   print('调用__init__,实例已经创建过了:', __instance)

 @classmethod
 def get_instance(cls):
  # 调用get_instance类方法的时候才会生成Singleton实例
  if not cls.__instance:
   cls.__instance = Singleton()
  return cls.__instance

以上这篇Python 用__new__方法实现单例的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python和C语言混合编程实例
Jun 04 Python
Python中的模块和包概念介绍
Apr 13 Python
Python教程之全局变量用法
Jun 27 Python
Mac中Python 3环境下安装scrapy的方法教程
Oct 26 Python
Python解决线性代数问题之矩阵的初等变换方法
Dec 12 Python
python设置环境变量的原因和方法
Jun 24 Python
Django的性能优化实现解析
Jul 30 Python
安装完Python包然后找不到模块的解决步骤
Feb 13 Python
Django 后台带有字典的列表数据与页面js交互实例
Apr 03 Python
Python GUI之tkinter窗口视窗教程大集合(推荐)
Oct 20 Python
如何将numpy二维数组中的np.nan值替换为指定的值
May 14 Python
Python 多线程处理任务实例
Nov 07 Python
python实现图像高斯金字塔的示例代码
Dec 11 #Python
Pycharm plot独立窗口显示的操作
Dec 11 #Python
Python OpenCV中的numpy与图像类型转换操作
Dec 11 #Python
使用python操作lmdb对数据读取的实例
Dec 11 #Python
PyTorch 中的傅里叶卷积实现示例
Dec 11 #Python
python中append函数用法讲解
Dec 11 #Python
python实现图像随机裁剪的示例代码
Dec 10 #Python
You might like
发布一个迷你php+AJAX聊天程序[聊天室]提供下载
2007/07/21 PHP
CI框架中redis缓存相关操作文件示例代码
2016/05/17 PHP
浅谈PHP中的数据传输CURL
2016/09/06 PHP
yii框架结合charjs实现统计30天数据的方法
2020/04/04 PHP
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
动态加载外部javascript文件的函数代码分享
2011/07/28 Javascript
Jquery图形报表插件 jqplot简介及参数详解
2012/10/10 Javascript
javascript时间自动刷新实现原理与步骤
2013/01/06 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
js 获取radio按钮值的实例
2013/08/17 Javascript
javascript的函数作用域
2014/11/12 Javascript
JavaScript中的Web worker多线程API研究
2014/12/06 Javascript
jQuery制作效果超棒的手风琴折叠菜单
2015/04/03 Javascript
JavaScript让Textarea支持tab按键的方法
2015/06/26 Javascript
浏览器中url存储的JavaScript实现
2015/07/07 Javascript
jQuery的选择器中的通配符[id^='code']或[name^='code']及jquery选择器总结
2015/12/24 Javascript
基于Turn.js 实现翻书效果实例解析
2016/06/20 Javascript
JS动态加载脚本并执行回调操作
2016/08/24 Javascript
基于JS实现的随机数字抽签实例
2016/12/08 Javascript
微信小程序实现一张或多张图片上传(云开发)
2019/09/25 Javascript
JS实现动态倒计时功能(天数、时、分、秒)
2019/12/12 Javascript
vue实现拖拽效果
2019/12/23 Javascript
Vue 同步异步存值取值实现案例
2020/08/05 Javascript
微信小程序实现自定义动画弹框/提示框的方法实例
2020/11/06 Javascript
利用 JavaScript 实现并发控制的示例代码
2020/12/31 Javascript
原生js实现滑块区间组件
2021/01/20 Javascript
[03:09]2014DOTA2国际邀请赛 赛场上的美丽风景线 中国Coser也爱DOTA2
2014/07/20 DOTA
[01:32]DOTA2 2015国际邀请赛中国区预选赛第四日战报
2015/05/29 DOTA
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
利用PyCharm操作Github(仓库新建、更新,代码回滚)
2019/12/18 Python
详解Python+Selenium+ChromeDriver的配置和问题解决
2021/01/19 Python
详解HTML5中div和section以及article的区别
2015/07/14 HTML / CSS
公务员诚信承诺书
2014/05/26 职场文书
员工薪酬激励方案
2014/06/13 职场文书
放假通知
2015/04/14 职场文书
Nginx 502 Bad Gateway错误原因及解决方案
2021/03/31 Servers