python __new__ __init__
写过python类的都会知道__init__,可能也了解__new__。我之前也了解__new__,但只做的它发生在__init__之前。其他的就比较模糊了
今天在学习单例模式时,看到有人用__new__去实例化,也有人用__init__去初始化,甚为奇怪,就查了一下别人的文章,总结一下。
简单来说,就是__new__负责返回一个实例,__init__负责初始化返回的那个实例,就是给返回的实例加上一些属性。__init__方法必须覆写,而__new__方法一般在__init__之前自动执行。如果__new__不能正确返回对象,__init__就不会调用,除非我们自己覆写了__new__,没有正确返回实例,否则不会出现这种情况。
例子来一发
class Human(object):
def __init__(self,n,a):
print "__init__ called"
self.name = n
self.age = a
def __new__(cls, name,age):
print "__new__ called"
return super(Human,cls).__new__(cls,name,age)
def tell(self):
print "My nama is %s,my age is %d"%(self.name,self.age) h = Human("lll",11) 输出:
_new__ called
__init__ called
这个就是我们经常用到的__init__,从输出结果显而易见,__new__先调用,__init__后调用。当我们去实例化一个对象时,基本过程是:
1.h = Human("lll",11)
2.有了第一步后,python解释器会立马去调用__new__,这个方法会返回一个Human的实例,并且给这个实例绑定了属性,这里就是name和age两个属性。方法的调用一般就是super(Human,cls).__new__(cls,name,age)这种格式。
3.__init__会接收到__new__返回的实例对象,和已经绑定的属性,然后给这些属性赋值,就是self.name = n ,self.age = a,给name属性赋值传递进来的n,age属性赋值传递进来的a。到此一个对象就建立完毕,可以用这个对象去调用其他方法了
所以__init__主要是用于初始化对象,给属性赋值,或者做一些比如print的事情,属于实例级别的方法__init__没有返回,__new__是生产一个实例,属于类级别的方法。__new__有返回值,返回新的对象。
刚才的__new__我们平时是不会去写出来的,属于自动调用。但是,有时候我们并不想让它去自动调用,就必须覆写它。
比如,如果我们的类继承自int,str,tuple这些类时,这些类是不可变的,所以在产生实例时他就是不可变的,但是我们继承了不可变的类又想让它可变,就只能去覆写它的__new__
比如我想判断一个数字是不是正数,就要继承int(可以保证是一个数字),然后在初始化中去判断,不是专门写一个函数去判断。
class ifPositive(int):
def __init__(self,value):
super(ifPositive,self).__init__(self,True if value>0 else False) i = ifPositive(3)
返回的是3,不是我们期待的1(此处不是返回True,是1,如果不是正数则返回0)
下面通过覆写__new__方法实现功能
class ifPositive(int):
def __new__(cls,value): 这里的第一个参数默认是cls
return super(ifPositive,cls).__new__(cls,True if value>0 else False) 此处一定要加return i = ifPositive(2)
返回1
i = ifPositive(-1)
返回0
查这两个方法时也看到__call__,此处也补充一下
一个类实现了这个函数,那么它的实例就多了一个功能,可以当作函数来用,直接在对象后面加上括号,里面就是__call__的参数,就会返回__call__方法的结果。还就拿上面的Human类,比如我给那个Human类加了一个方法
def __call__(self,attr):
if attr == "name":
return self.name
else:
return self.age h = Human("lll",11)
print h("name")
会返回“lll"
python __new__ __init__的更多相关文章
- python __new__ __init__ __del__
1.python实例化顺序是.__new__ -->__init__ --> __del__ 2.如果重写new没return,就实例化不成功
- python __new__ __init__ 区别
参数 __new__的第一个占位参数是class对象 __init__的第一个占位参数是class的实例对象 其他的参数应一致 作用 __new__ 用来创建实例,在返回的实例上执行__init__, ...
- python __new__以及__init__
@[深入Python]__new__和__init__ 1 2 3 4 5 6 7 8 class A(object): def __init__(self): print & ...
- python中__init__.py文件的作用
问题 在执行models.py时,报ImportError:No module named transwarp.db的错误,但明明transwarp下就有db.py文件,路径也没有错误.真是想不通.后 ...
- Python中__init__方法介绍
本文介绍Python中__init__方法的意义. __init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的 初始化 .注意,这个名称的开始和结尾 ...
- Python的__init__.py用法
python中包的引入,对于大型项目中都会使用到这个功能,把实现不同功能的python文件放在一起,组成不同lib库,然后在其他地方调用. 包,python源文件+__init__.py 模块,pyt ...
- Python中__init__.py文件的作用详解
转自http://www.jb51.net/article/92863.htm Python中__init__.py文件的作用详解 http://www.jb51.net/article/86580. ...
- 转载:【学习之家】Python中__init__.py文件的作用
Python中__init__.py文件的作用详解 Python中__init__.py文件的作用详解 来源:学习之家 作者:xuexi110 人气:357 发布时间:2016-09-29 摘要:__ ...
- [深入Python]__new__和__init__
class A(object): def __init__(self): print "init" def __new__(cls,*args, **kwargs): print ...
随机推荐
- PHP获取当前页面的网址
PHP获取当前页面的网址 function GetCurUrl() { $url = 'http://'; if(isset($_SERVER['HTTPS']) AND $_SERVER['HTTP ...
- Ubuntu Eclipse ns3编译中 遇到的OSError 系列问题
问题1:Permission denied 解决方法:修改文件权限,利用 chmod 命令 修改在 /home/wasdns/workspace/MyNS3_Mac/ns-3.25 (eclipse工 ...
- C# Int转Enum
Int-->Enum (1)可以强制转换将整型转换成枚举类型. 例如:Colors color = (Colors)2 ,那么color即为Colors.Blue (2)利用Enum的静态方法T ...
- Hibernate 由实体类与配置文件的配置关系生成数据库中的表
import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; public class ...
- 遇到Io阻塞时会切换任务之【爬虫版】
#! /usr/bin/env python3 # -*- coding:utf- -*- from urllib import request import gevent,time from gev ...
- linux 多进程fork
对于父进程,fork函数返回了子程序的进程号,而对于子程序,fork函数则返回零,这样,对于程序,只要判定fork函数的返回值,就知道自己是处于父进程还是子进程中.
- UTC和GMT时间辨析
一.UTC和GMT 每个地区都有自己的本地时间,在网上以及无线电通信中时间转换的问题就显得格外突出. 整个地球分为二十四时区,每个时区都有自己的本地时间.在国际无线电通信场合,为了统一起见,使用一个统 ...
- EsayUI + MVC + ADO.NET(仓储基础接口)
1.RepositoryFramework(仓储接口:无外乎就是CRUD) 1.IAddRepository(添加接口) using System; namespace Notify.Infras ...
- 一步一步实现JS拖拽插件
js拖拽是常见的网页效果,本文将从零开始实现一个简单的js插件. 一.js拖拽插件的原理 常见的拖拽操作是什么样的呢?整过过程大概有下面几个步骤: 1.用鼠标点击被拖拽的元素 2.按住鼠标不放,移动鼠 ...
- Codeforces 832D - Misha, Grisha and Underground
832D - Misha, Grisha and Underground 思路:lca,求两个最短路的公共长度.公共长度公式为(d(a,b)+d(b,c)-d(a,c))/2. 代码: #includ ...