python中__init__()、__new__()、__call__()、__del__()几个魔法方法的用法
关于__new__()的用法参考:
http://www.myhack58.com/Article/68/2014/48183.htm
正文:
一、__new__()的用法:
__new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。
# encoding:utf-
class A(object):
def __new__(cls, x):
print 'this is in A.__new__, and x is ', x
return super(A, cls).__new__(cls)
def __init__(self, y):
print 'this is in A.__init__, and y is ', y
class C(object):
def __new__(cls, n):
print 'this is in C.__new__, and n is ', n
return super(C, cls).__new__(cls)
def __init__(self, a):
print 'this is in C.__init__, and a is ', a
class B(A):
def __new__(cls, z):
print 'this is in B.__new__, and z is ', z
return A.__new__(cls, z)
def __init__(self, m):
print 'this is in B.__init__, and m is ', m
# class B(A):
# def __new__(cls, z):
# print 'this is in B.__new__, and z is ', z
# return object.__new__(cls)
# def __init__(self, m):
# print 'this is ni B.__init__, and m is ', m
if __name__ == '__main__':
a = A()
print
b = B()
print type(b)
执行的结果为:
==================== <class '__main__.B'>
说明:
1.定义A类作为下面类的父类,A类继承object类,因为需要重写A类的__new__()函数,所以需要继承object基类,成为新式类,经典类没有__new__()函数;
2.子类在重写__new__()函数时,写return时必须返回有继承关系的类的__new__()函数调用,即上面代码中的B类继承自A类,则重写B类的__new__()函数,写return时,只能返回A.__new__(cls)或者object.__new__(cls),不能返回C类的;
3.由注释掉的代码执行结果可以看出,B类虽然继承自A类,但是如果没有重写B类的__new__()函数,则默认继承的仍是object基类的__new__(),而不是A的;
4.B类的__new__()函数会在B类实例化时被调用,自动执行其中的代码语句,但是重写__new__()函数不会影响类的实例化结果,也就是说不管写return时返回的是A的还是object的,B类的实例化对象就是B类的,而不会成为A类的实例化对象;只是在实例化时,如果返回的是A.__new__(cls),则会执行A类中定义的__new__()函数;
5.__new__()函数确定了类的参数的个数,object类默认定义的__new__()函数的参数为(cls, *more),但如果在子类中重写了__new__(cls, x), 则实例化类时,需要传入一个x参数,而__init__()函数接受到的有两个参数,一个是实例化生成的实例对象self代替,一个是传入的实参x的值;
>>>
>>> class A(object):
def __init__(self, x):
self.x = x
print '__init__ called.'
def foo(self):
print self.x
>>>
>>> a = A(')
__init__ called.
>>>
>>> a.foo()
>>>
在A('123')实例化类时,自动调用__init__()方法定义的self.x = x和print '__init__ called.',我们能看到‘__init__ called.’被打印,看不到self.x = x的执行,但是在调用a.foo()时,能执行成功,就是拜self.x = x的功能所赐;因为如果没有__init__()方法中的self.x = x,实例对象将无法追溯到foo()函数中的self.x是从哪里来的,从而会报错;也就是在__init__()函数中将外部传入的参数x赋值给self.x,从而是self.x在类A中畅行无阻;
三.__call__()的用法
__call__()方法能够让类的实例对象,像函数一样被调用;
>>>
>>> class A(object):
def __call__(self, x):
print '__call__ called, print x: ', x
>>>
>>> a = A()
>>> a(')
__call__ called, print x:
>>>
看a('123')这是函数的调用方法,这里a实际上是类对象A的实例对象,实例对象能想函数一样传参并被调用,就是__call__()方法的功能;
四、__del__()的用法
如果__new__()和__init__()函数时类的构造函数(即在类实例化时自动执行函数中定义的内容),那么__del__()是类的析构函数,是python垃圾回收机制的实际应用,当类的所有引用都被删除后,该类就会被系统从内存中删除,注意是所有的引用都被删除哦,而不是每一次删除;
>>> class D(object):
def __init__(self):
print 'this is D.__init__()'
def __del__(self):
print 'this is D.__del__()'
>>>
>>> d = D()
this is D.__init__()
>>>
>>> d2 = d
>>> d3 = d
>>>
>>> del d
>>> del d2
>>> del d3
this is D.__del__()
>>>
将D()实例化对象赋值给d,后d2,d3都是指向D()的这次实例化对象,删除d和d2的引用都不会触发__del__()函数,最后一个d3的引用被删除,就会触发__del__(),此时D()的这一次实例化的对象就被清除;
最后:
用一段简单的代码,来总体感受一下三个方法的用法和区别:
>>>
>>> class A(object):
def __init__(self, x):
print 'x in __init__', x
def __new__(cls, y):
print 'y in __new__', y
return super(A, cls).__new__(cls)
def __call__(self, z):
print 'z in __call__', z
def __del__(self):
print 'this is in A.__del__()'
>>>
>>> A(')('abc')
y
x
z in __call__ abc
this is in A.__del__()
>>>
由执行结果可以看出,虽然__init__()方法定义在__new__()方法之前,但是结果中先展示了__new__()方法的执行结果;
python中__init__()、__new__()、__call__()、__del__()几个魔法方法的用法的更多相关文章
- Python中被双下划线包围的魔法方法
基本的魔法方法 __new__(cls[, ...]) 用来创建对象 1. __new__ 是在一个对象实例化的时候所调用的第一个方法 2. 它的第一个参数是这个类,其他的参数是用来直接传递给 __i ...
- Python中的__new__和__init__
Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...
- Python中的__new__()方法与实例化
@Python中的__new__()方法与实例化 __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...
- python中__init__.py文件的作用
问题 在执行models.py时,报ImportError:No module named transwarp.db的错误,但明明transwarp下就有db.py文件,路径也没有错误.真是想不通.后 ...
- Python中__init__方法介绍
本文介绍Python中__init__方法的意义. __init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的 初始化 .注意,这个名称的开始和结尾 ...
- 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中模拟enum枚举类型的5种方法分享
这篇文章主要介绍了Python中模拟enum枚举类型的5种方法分享,本文直接给出实现代码,需要的朋友可以参考下 以下几种方法来模拟enum:(感觉方法一简单实用) 复制代码代码如下: # way1 ...
- Python中多个列表与字典的合并方法
Python中多个列表与字典的合并方法 1多列表的合并 1)a+=b a=['] b = ['] a += b print(a) >>>['] 2) a.extend(b) a=[' ...
随机推荐
- ElasticSearch(八):springboot集成ElasticSearch集群并使用
1. 集群的搭建 见:ElasticSearch(七) 2. springboot配置集群 2.1 创建springboot项目,使用idea创建,不过多介绍(创建项目时候建议不要勾选elastics ...
- PHP vs Node.js
网络正在处于一个日新月异的发展时代.服务器端开发人员在选择语言的时候非常困惑,有长期占主导地位的语言,例如C.Java和Perl,也有专注于web开发的语言,例如Ruby.Clojure和Go.只要你 ...
- idea_快捷键default&eclipse
关键字: SpringMybatisplusRedisApplicationTests github关键字(springboot拦截器完整项目): implements WebMvcConfigure ...
- Descriptor&web.xml
Deployment Descriptor部署描述符: - 部署描述符是要部署到Web容器或EJB容器的Web应用程序或EJB应用程序的配置文件. - 部署描述符应包含EJB应用程序中所有企业bean ...
- vector容器的用法以及动态数组
vector容器不必去管大小 string申明的数组已经是动态的了 若是int类型的话,需要 cin>>N: int a[N]会出错 ,必须是int *p = new int[N] 然后再 ...
- 极快瑞的函数式编程,Jquery涉及的一些函数
$(function(){ 一些实现功能的代码:})————————————文档载入完成后执行的函数.$(function(){}) 是 $(document).ready(function(){}) ...
- sqlserver linux 容器运行
sqlserver linux 版本的容器大小目前已经相对比较小了,对于开发来说已经比较方便了 docker-compose 文件 version: "3" services: d ...
- 比jsonpath 更方便的json 数据查询JMESPath 使用
类似xml 的xpath json 有jsonpath 都是为了方便进行数据查询,但是jsonpath 的功能 并不是很强大,如果为了方便查询可以使用jmespath. 以下为简单使用: 查询格式 ...
- jquery选择器之属性过滤选择器详解
代码如下: <style type="text/css"> /*高亮显示*/ .highlight{ } </style> 复制代码代码如下 ...
- java 的关键字 native
native native 关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中.Java语言本身不能对操作系统底层进行访问和操作,但是可 ...