__init__和__new__
一、__init__方法是什么
__init__方法通常用在初始化一个类实例的时候, class Person(object):
"""Silly Person""" def __init__(self, name, age):
print('__init__ called.')
self.name = name
self.age = age def __str__(self):
return '<Person: %s(%s)>' % (self.name, self.age) if __name__ == '__main__':
piglei = Person('piglei', 24)
print(piglei) """
__init__ called.
<Person: piglei(24)>
""" 二、 __new__方法是什么?
__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而__new__方法正是创建这个类实例的方法 class Person(object):
"""Silly Person""" def __new__(cls, name, age):
print('__new__ called.')
return super(Person, cls).__new__(cls) def __init__(self, name, age):
print('__init__ called.')
self.name = name
self.age = age def __str__(self):
return '<Person: %s(%s)>' % (self.name, self.age) if __name__ == '__main__':
piglei = Person('piglei', 24)
print(piglei) 执行结果
"""
__new__ called.
__init__ called.
<Person: piglei(24)>
"""
通过运行这段代码,我们可以看到,__new__方法的调用时发生在__init__之前的,其实当你实例化一个类的时候,具体的执行逻辑是这样的:
1 p=Person(name,age)
2 首先执行使用name和age参数来执行Person类的__new__方法,这个方法会返回Person类的一个实例(通常情况下是使用super(Persion,cls).__new__(cls)这样的方式)
3 然后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是__init__里面的self
所以,__init__和__new__最主要的区别在于:
1 __init__通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性,做一些额外的操作,发生在类实例被创建完以后,它是实例级别的方法
2 __new__通常用于控制生成一个新实例的过程。它是类级别的方法 三 __new__的作用
按照python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int,str,tuple),提供给你一个自定义这些类的实例化过程的途径,还有就是实现自定义的metaclass
首先来看一下第一个功能,我们用int来作为一个例子
假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码 class PositiveInteger(int):
def __init__(self,value):
super(PositiveInteger, self).__init__() i = PositiveInteger(-3)
print(i)
运行后会发现,结果根本不是我们想的那样,我们仍然得到了-3。这是因为对于int这种不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用
修改后的代码
class PositiveInteger(int):
def __new__(cls, value):
return super(PositiveInteger, cls).__new__(cls, abs(value))
i = PositiveInteger(-3)
print(i) 通过重载__new__方法,我们实现了需要的功能
另外一个作用,关于自定义metaclass。 四、用__new__来实现单例
事实上,我们理解了__new__方法后,我们可以用它来实现设计模式中的单例模式
因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,可以很简单的实现单例模式
class Singleton(object):
def __new__(cls, *args, **kwargs):
#每次实例化时,都会返回同一个instance对象
if not hasattr(cls,'instance'):
cls.instance=super(Singleton, cls).__new__(cls)
return cls.instance
obj1=Singleton()
obj2=Singleton() obj1.attr1='value1'
print(obj1.attr1,obj2.attr1)
print(obj1 is obj2)
"""
value1 value1
True
"""
obj1和obj2是同一个实例
__init__和__new__的更多相关文章
- python中的__init__ 、__new__、__call__小结
这篇文章主要介绍了python中的__init__ .__new__.__call__小结,需要的朋友可以参考下 1.__new__(cls, *args, **kwargs) 创建对象时调用,返回 ...
- 详解python中的__init__与__new__方法
一.__init__和__new__方法执行的顺序? 在面向对象中介绍了关于对象创建的过程,我们知道__new__方法先于__init__方法执行. 二.__new__方法是什么? 首先,我们先来看下 ...
- Python中的__init__和__new__
一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: # -*- c ...
- 简析 __init__、__new__、__call__ 方法
简析 __init__.__new__.__call__ 方法 任何事物都有一个从创建,被使用,再到消亡的过程,在程序语言面向对象编程模型中,对象也有相似的命运:创建.初始化.使 用.垃圾回收,不同的 ...
- python 的__init__ 和__new__ 区别
在此介绍一下 __init__ 和 __new__ 先后调用的区别 代码如下: # __init__ 和 __new__的区别 # 通常在编代码时,__init__ 较为常见,但是__new__却 ...
- python中的__init__和__new__的区别
一.__init__ 方法是什么?(init前后的线是双下划线) 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例 ...
- __init__、__new__、__call__ 方法
__init__方法 __init__方法负责对象的初始化,系统执行该方法前,其实该对象已经存在了,要不然初始化什么东西呢?先看例子: # class A(object): python2 必须显示地 ...
- Python基础(十) __init__与__new__区别
__init__与__new__区别: __init__在python,其实是,在实例化之后执行的,用来初始化一些属性,相当于构造函数,但是又不一样 细心一些,通过参数会有所发现,其实__init__ ...
- Python入门之面向对象的__init__和__new__方法
Python入门之面向对象的__init__和__new__方法
- Python中__init__和__new__的区别详解
__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如: # -*- cod ...
随机推荐
- DatabaseFactory.CreateDatabase 方法操作数据库
using Microsoft.Practices.EnterpriseLibrary.Data;using Microsoft.Practices.EnterpriseLibrary.Data.Sq ...
- js基础系列框架:JS重要知识点(转载)
这里列出了一些JS重要知识点(不全面,但自己感觉很重要).彻底理解并掌握这些知识点,对于每个想要深入学习JS的朋友应该都是必须的. 讲解还是以示例代码搭配注释的形式,这里做个小目录: JS代码预解析原 ...
- linux 下安装svn服务
鉴于在搭建时,参考网上很多资料,网上资料在有用的同时,也坑了很多人 本文的目的,也就是想让后继之人在搭建svn服务器时不再犯错,不再被网上漫天的坑爹作品所坑害,故此总结 /******开始****** ...
- CDH配置JAVA_HOME
jdk成功安装 java -version 正确显示版本 echo $JAVA_HOME 正确输出路径 但CDH链接数据库还是报错: Error: JAVA_HOME is not set and ...
- 【转】Monkey测试4——Monkey命令行可用的全部选项
Monkey命令行可用的全部选项 常规 --help 列出简单的用法. -v 命令行的每一个-v将增加反馈信息的级别. Level 0(缺省值)除启动提示.测试完成和最终结果之外,提供较少信息. Le ...
- 结果集(ResultSet)用法
结果集(ResultSet)是数据中查询结果返回的一种对象,可以说结果集是一个存储查询结果的对象,但是结果集并不仅仅具有存储的功能,他同时还具有操纵数据的功能,可能完成对数据的更新等. 结果集读取数据 ...
- Working with JSON in C# & VB
Introduction Whilst JSON is a compact and easy to read cross-language storage and data exchange form ...
- libevent在windows下用visual studio编译时出现error C2894错误的原因与解决方法
libevent是一个使用很广泛的网络库,今天想了解下它.于是去git clone了一份源码,用vs2005的命令行:nmake -f makefile.nmake编译之,顺利编译通过,生成三个静态库 ...
- 服务器之ipmitool
一般命令 raw #发送一个原始的IPMI请求,并且打印回复信息. Lan #配置网络(lan)信道(channel) chassis #查看底盘的状态和设置电源 event #向BMC发送一个已经定 ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...