由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别
之前通过读书,了解到在Python中可以通过__new__方法来实现单例模式,代码一个示例如下,我就有了几个疑问,什么是单例模式?__new__方法是用来做什么的?用__new__方法实现的单例模式,比如下面的MyClass类,会对类的初始化有影响吗?会对类的实例方法、类方法、静态方法有影响吗?下面会说下我对这些概念的理解,如有错误,欢迎交流指出,在此表示感谢。
class SingleTon(object):
_instance = {} def __new__(cls, *args, **kwargs):
if cls not in cls._instance:
cls._instance[cls] = super(SingleTon, cls).__new__(cls, *args, **kwargs)
print cls._instance
return cls._instance[cls] class MyClass(SingleTon):
class_val = 22
首先说下单例模式,单例模式是确保一个类只有一个实例,并且这个实例是自己创造的,在系统中用到的都是这个实例。单例模式是设计模式的一种,关于设计模式和单例模式更具体的内容,可以查看相关的书本,在后面我也要好好学习一下这些东西。
下面主要说下__new__是用来干什么的,在Python中,__new__是用来创造一个类的实例的,而__init__是用来初始化这个实例的。既然__new__用来创造实例,也就需要最后返回相应类的实例,那么如果返回的是其他类的实例,结果如何呢?见下面的代码。以下代码运行后,首先打印出NoReturn __new__然后打印出other instance,最后通过type(t)可以看到t的类型是<class '__main__.Other'>,可以知道如果__new__中不返回本类的实例的话,是没法调用__init__方法的。想要返回本类的实例,只需要把以下代码中12行的Other()改成super(NoReturn, cls).__new__(cls, *args, **kwargs)即可。
class Other(object):
val = 123 def __init__(self):
print 'other instance' class NoReturn(object): def __new__(cls, *args, **kwargs):
print 'NoReturn __new__'
return Other() def __init__(self, a):
print a
print 'NoReturn __init__' t = NoReturn(12)
print type(t)
最后来说用__new__方法实现的单例模式,会对实例方法,类方法,静态方法,实例变量和类变量有影响吗?答案是对相应的方法是没有影响的,但是如果用不同的变量都初始化了这个实例,在后面的变量中修改实例变量和类变量的话,前面的也会相应修改,而这也正好符合单例,无论多少个变量指向了这个实例,他们指向的是同一个。在__new__中产生完实例后,每次初始化实例对象,都是产生的同一个实例,而这个实例中相关的方法、变量还是和普通的实例一样使用。测试代码以及输出如下:
class MyClass(SingleTon):
class_val = 22 def __init__(self, val):
self.val = val def obj_fun(self):
print self.val, 'obj_fun' @staticmethod
def static_fun():
print 'staticmethod' @classmethod
def class_fun(cls):
print cls.class_val, 'classmethod' if __name__ == '__main__':
a = MyClass(1)
b = MyClass(2)
print a is b # True
print id(a), id(b) # 4367665424 4367665424
# 类型验证
print type(a) # <class '__main__.MyClass'>
print type(b) # <class '__main__.MyClass'>
# 实例方法
a.obj_fun() # 2 obj_fun
b.obj_fun() # 2 obj_fun
# 类方法
MyClass.class_fun() # 22 classmethod
a.class_fun() # 22 classmethod
b.class_fun() # 22 classmethod
# 静态方法
MyClass.static_fun() # staticmethod
a.static_fun() # staticmethod
b.static_fun() # staticmethod
# 类变量
a.class_val = 33
print MyClass.class_val #
print a.class_val #
print b.class_val #
# 实例变量
print b.val #
print a.val #
由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别的更多相关文章
- Python中使用__new__实现单例模式并解析
阅读文章前请先阅读 Python中类方法.__new__方法和__init__方法解析 单例模式是一个经典设计模式,简要的说,一个类的单例模式就是它只能被实例化一次,实例变量在第一次实例化时就已经固定 ...
- Python __new__ 实现单例模式 python经典面试题
话不多说,上代码 class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance' ...
- python 内建函数__new__的单例模式
今天好奇__init__和__new__的区别是什么? 我了解到: __init__:只是单纯的返回一个类对象的实例,是在__new__之后调用的 __new__:创建一个类对象实例, class S ...
- [python实现设计模式]-1. 单例模式
设计模式中,最简单的一个就是 “单例模式”, 那么首先,就实现一下单例模式. 那么根据个人的理解,很快就写出第一版. # -*- coding: utf-8 -*- class Singleton(o ...
- python面向对象进阶 反射 单例模式 以及python实现类似java接口功能
本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和特性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存 ...
- Python学习笔记:单例模式
单例模式:一个类无论实例化多少次,返回的都是同一个实例,例如:a1=A(), a2=A(), a3=A(),a1.a2和a3其实都是同一个对象,即print(a1 is a2)和print(a2 is ...
- exec , 元类,__new__, __call__ , 单例模式 , 异常
1,类也是对象 ''' 动态语言 可以在运行期间 动态生成类 修改对象属性 静态语言 ''''' ''' type(object_or_name, bases, dict) type(object) ...
- python中几种单例模式的实现
单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...
- python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。
单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样. 如下: 源码: class A(object): d ...
随机推荐
- 开源纯C#工控网关+组态软件(三)加入一个新驱动:西门子S7
一. 引子 首先感谢博客园:第一篇文章.第一个开源项目,算是旗开得胜.可以看到,项目大部分流量来自于博客园,码农乐园,名不虚传^^. 园友给了我很多支持,并提出了很好的改进意见.现加入屏幕分辨率自 ...
- MVC中View界面数据呈现示例
@using System.Text; @model List<MvcShopping.Models.ProductCategory> @{ ViewBag.Title = "测 ...
- Django Cookie 和 Sessions 应用
在Django里面,使用Cookie和Session看起来好像是一样的,使用的方式都是request.COOKIES[XXX]和request.session[XXX],其中XXX是您想要取得的东西的 ...
- 当 ReactJS 遇到 TypeScript
由于本人应用项目主要是2B的web应用程序, 所以以下暂不谈react的服务端渲染和react navie, 先说说ReactJS: React 的组件化和 数据单向绑定 的模式(flux) 使应用 ...
- php中各种定义变量的方法
1.定义常量define("CONSTANT", "Hello world."); 常量只能包含标量数据(boolean,integer,float 和 s ...
- Android 性能优化概念(1)
http://www.open-open.com/lib/view/open1421723359718.html#_label0 阅读目录 0)Render Performance 1)Underst ...
- 浅谈oracle树状结构层级查询测试数据
浅谈oracle树状结构层级查询 oracle树状结构查询即层次递归查询,是sql语句经常用到的,在实际开发中组织结构实现及其层次化实现功能也是经常遇到的,虽然我是一个java程序开发者,我一直觉得只 ...
- Java限流策略
概要 在大数据量高并发访问时,经常会出现服务或接口面对暴涨的请求而不可用的情况,甚至引发连锁反映导致整个系统崩溃.此时你需要使用的技术手段之一就是限流,当请求达到一定的并发数或速率,就进行等待.排队. ...
- Codeforces Round #439 (Div. 2) C DP(图论)
C. The Intriguing Obsession time limit per test 1 second memory limit per test 256 megabytes input s ...
- javascript倒计时调转页面
<html><head><meta http-equiv="Content-Type" content="text/html; charse ...