关于__new__()的用法参考:

http://www.myhack58.com/Article/68/2014/48183.htm

正文:

一、__new__()的用法:

__new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。

如果将类比喻为工厂,那么__init__()方法则是该工厂的生产工人,__init__()方法接受的初始化参 数则是生产所需原料,__init__()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 __new__()则是生产部经理,__new__()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出 货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。
# encoding:utf-8

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(100)
print '=' * 20
b = B(200)
print type(b)

执行的结果为:

this is in A.__new__, and x is  100
this is in A.__init__, and y is 100
====================
this is in B.__new__, and z is 200
this is in A.__new__, and x is 200
this is in B.__init__, and m is 200
<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的值;

__new__()方法的特性:
   __new__()方法是在类准备将自身实例化时调用。
   __new__()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。是因为无论怎样重写类的__new__()函数,追溯到源头都是继承自object的__new__()函数,而object类中定义的__new__()函数就被定义成了静态函数,被@stacitmethod修饰

   类的实例化和它的构造方法通常都是这个样子:
class MyClass(object):
   def __init__(self, *args, **kwargs):
       ...
# 实例化
myclass = MyClass(*args, **kwargs)
正如以上所示,一个类可以有多个位置参数和多个命名参数,而在实例化开始之后,在调用 __init__()方法之前,Python首先调用__new__()方法:
def __new__(cls, *args, **kwargs):
   ...
第一个参数cls是当前正在实例化的类。
   如果要得到当前类的实例,应当在当前类中的__new__()方法语句中调用当前类的父类 的__new__()方法。
例如,如果当前类是直接继承自object,那当前类的__new__()方法返回的对象应该为:
def __new__(cls, *args, **kwargs):
   ...
   return object.__new__(cls)
注意:
事实上如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时 ,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写 __new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。
而如果新式类中重写了__new__()方法,那么你可以自由选择任意一个的其他的新式类(必定要是 新式类,只有新式类必定都有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__() 方法)的__new__()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死 循环。具体看以下代码解释:
class Foo(object):
    def __init__(self, *args, **kwargs):
        ...
    def __new__(cls, *args, **kwargs):
        return object.__new__(cls, *args, **kwargs)    
    
# 以上return等同于 
# return object.__new__(Foo, *args, **kwargs)
    
class Child(Foo):
    def __new__(cls, *args, **kwargs):
        return object.__new__(cls, *args, **kwargs)
# 如果Child中没有定义__new__()方法,那么会自动调用其父类的__new__()方法来制造实例,即Foo.__new__(cls, *args, **kwargs)。
# 在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环。因此必须避免类似以下的写法:
# 在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)。Child同理。
# 使用object或者没有血缘关系的新式类的__new__()是安全的,但是如果是在有继承关系的两个类之间,应避免互调造成死循环,例如:(Foo)return Child.__new__(cls), (Child)return Foo.__new__(cls)。
class Stranger(object):
    ...
# 在制造Stranger实例时,会自动调用 object.__new__(cls)
通常来说,新式类开始实例化时,__new__()方法会返回cls(cls指代当前类)的实例,然后该类的 __init__()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入__new__ ()方法中接收的位置参数和命名参数。
注意:如果__new__()没有返回cls(即当前类)的实例,那么当前类的__init__()方法是不会被调用 的。如果__new__()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方 法。
class Foo(object):
    def __init__(self, *args, **kwargs):
        ...
    def __new__(cls, *args, **kwargs):
        return object.__new__(Stranger, *args, **kwargs)  
    
class Stranger(object):
    ...
    
foo = Foo()
print type(foo)    
    
# 打印的结果显示foo其实是Stranger类的实例。
# 因此可以这么描述__new__()和__ini__()的区别,在新式类中__new__()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()使其丰满。
# 如果以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地。而__init__()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,__init__()负责大楼的细节设计,建造,装修使其可交付给客户;
 
二、__init__()的用法
  __init__()是python的一个构造方法,在定义类时,用于初始化的一些操作;它能实现的功能及原理相对来讲也是比较简单一点,就是在实例化该类时,自动执行__init__()方法定义的内容;但是注意__init__()一般不用户返回return;
>>>
>>> class A(object):
def __init__(self, x):
self.x = x
print '__init__ called.'
def foo(self):
print self.x >>>
>>> a = A('123')
__init__ called.
>>>
>>> a.foo()
123
>>>

  在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('123')
__call__ called, print x: 123
>>>

  看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('123')('abc')
y in __new__ 123
x in __init__ 123
z in __call__ abc
this is in A.__del__()
>>>

  由执行结果可以看出,虽然__init__()方法定义在__new__()方法之前,但是结果中先展示了__new__()方法的执行结果;

python中__init__()、__new__()、__call__()、__del__()用法的更多相关文章

  1. Python中的__new__和__init__

    Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...

  2. Python中的__new__()方法与实例化

    @Python中的__new__()方法与实例化   __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...

  3. Python中【__all__】的用法

    Python中[__all__]的用法 转:http://python-china.org/t/725 用 __all__ 暴露接口 Python 可以在模块级别暴露接口: __all__ = [&q ...

  4. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  5. python中__init__.py文件的作用

    问题 在执行models.py时,报ImportError:No module named transwarp.db的错误,但明明transwarp下就有db.py文件,路径也没有错误.真是想不通.后 ...

  6. Python中__init__方法介绍

    本文介绍Python中__init__方法的意义.         __init__方法在类的一个对象被建立时,马上运行.这个方法可以用来对你的对象做一些你希望的 初始化 .注意,这个名称的开始和结尾 ...

  7. Python中__init__.py文件的作用详解

    转自http://www.jb51.net/article/92863.htm Python中__init__.py文件的作用详解 http://www.jb51.net/article/86580. ...

  8. python中enumerate()函数用法

    python中enumerate()函数用法 先出一个题目:1.有一 list= [1, 2, 3, 4, 5, 6]  请打印输出:0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 打印输 ...

  9. Python中try...except...else的用法

    Python中try...except...else的用法: try:    <语句>except <name>:    <语句>          #如果在try ...

  10. Python中logging模块的基本用法

    在 PyCon 2018 上,Mario Corchero 介绍了在开发过程中如何更方便轻松地记录日志的流程. 整个演讲的内容包括: 为什么日志记录非常重要 日志记录的流程是怎样的 怎样来进行日志记录 ...

随机推荐

  1. Daily Scrum10 11.14

    昨天的任务已经完成,但是我们在完成任务的过程中确实遇到了困难.昨天我们发现无法连接sqlserver的时候,给罗杰老师发了邮件.老师也给我们提出了建议,给我们提供了一些参考.所以今天大家都在研究如何解 ...

  2. Scrum Meeting 10.30

    成员 今日任务 明日计划 用时 徐越 配置servlet环境,设计开发文档 设计开发文档,配置服务器,使得本地可以访问服务器 5h 武鑫 软件界面设计:学习使用Activity和Fragment 设计 ...

  3. OO学习第一阶段总结

    前言 虽然之前接触过java,也写过一些1000行左右的程序.可以说面向对象的思想和java的一些基本语法对我来说是没有难度的,但是这学期的面向对象依然给了我一个下马威.这几次的作业每次都很让我头疼. ...

  4. 20172308 实验二《Java面向对象程序设计 》实验报告

    20172308 2017-2018-2 <程序设计与数据结构>实验2报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 周亚杰 学号:20172308 实验教师:王 ...

  5. Sprint会议3

    昨天:熟悉了一下软件操作,设计了图标. 今天:今天满课,没有做什么实质性的进展. 遇到问题:由于没干什么,也没遇到什么问题.

  6. html border画三角形

    最近遇到了问题就是画推进条类似于

  7. C#窗体随机四则运算 (第四次作业)

    ---恢复内容开始--- 增量内容:1)处理用户的错误输入,比如输入字母或符号等,处理除法运算中分母为0的情况,处理结果为负数的情况,保证是小学水平不出现负数,比如不能出现5-8=-3这种情况:2)用 ...

  8. 软工实践-Beta 冲刺 (1/7)

    队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 1.界面的修改与完善 展示GitHub当日代码/文档签入记 ...

  9. 代码上传不到github远程仓库的经历和总结

    第二次的作业是分布式版本控制系统Git的安装与使用.一切都好端端地进行,知道最后的上传到给远程仓库时一直都上传失败.舍友也过来调试和助教的指导,依然不成功.我也上网进行了大量的翻查资料也未能成功.这是 ...

  10. java使用Cookie判断用户登录情况

    1.判断是否登录 public boolean isLogin() { Set<Cookie> cookies = this.browser.getCookies(); String JS ...