本篇主要想要详细的介绍一下关于类的魔法方法__new__()方法。

  在学习之前我们看一下Python3中关于object基类的__new__() 方法:

    @staticmethod # known case of __new__
def __new__(cls, *more): # known special case of object.__new__
""" Create and return a new object. See help(type) for accurate signature. """
pass

  上述描述:__new__()创建和返回一个新的对象。通俗说:该魔法属性是用来创建实例对象的。接下来我们看一下它的是如何创建对象的。

一、理解

  1、__new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前。

  即可以这样理解:Python中存在于类中的构造方法__init__()负责将类实例化,而在__init__()执行之前,__new__()负责制造这样的一个实例对象,以便__init__()去让该实例对象更加的丰富(为其添加属性等)。

  同时:__new__() 方法还决定是否要使用该__init__() 方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。

  2、__new__() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器。

    比喻

  

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

  

二、结构

  在Python中,若不重写类中的__new__()方法,其默认的结构时这样的:

class Foo(object):
def __new__(cls,*args,**kwagrs):
return super().__new__(cls,*args,**kwagrs)

  1、其第一个参数 cls 是当前正在实例化的类。 

  如果要得到当前类的实例,应当在当前类中的__new__()方法语句中调用当前类的父类 的__new__()方法。例如,如果当前类是直接继承自object,那当前类的__new__()方法返回的对象应该为:

class Foo(object):
def __new__(cls,*args,**kwagrs):
return object.__new__(cls,*args,**kwagrs)

  注:①、如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时 ,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写 __new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。

  ②、如果新式类中重写了__new__()方法,那么你可以自由选择任意一个的其他的新式类(必定要是 新式类,只有新式类必定都有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__() 方法)的__new__()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死 循环。

class A(object):
pass class B(A):
pass class C(B):
def __new__(cls,*args,**kwargs):
return super().__new__(cls, *args,**kwargs) # 等同于:
# return B.__new__(cls, *args,**kwargs)
# return A.__new__(cls, *args,**kwargs)
# return object.__new__(cls, *args,**kwargs)

  2、在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环。

  例如:

class Bar(object):
def __new__(cls,*agrs,**kwagrs):
return Bar.__new__(Foo,*agrs,**kwagrs)

  这样的话会造成 当Bar调用其自身的__new__() 方法制造实例时,又会跳到第二行去执行__new__(),当到第三行时,又跳到第二行去调用__new__(),这样不断的就会陷入死循环。

  3、Bar.__new__(Foo,*agrs,**kwagrs) ,指:使用哪个类(bar)的__new__()方法去制造谁的(Foo)实例对象。

  通常来说,新式类开始实例化时,__new__()方法会返回cls(cls指代当前类)的实例,然后该类的 __init__()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入__new__ ()方法中接收的位置参数和命名参数。

  注:如果__new__()没有返回cls(即当前类)的实例,那么当前类的__init__()方法是不会被调用 的。如果__new__()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方 法。

class Foo(object):
def __new__(cls,*args,**kwagrs):
return object.__new__(cls,*args,**kwagrs) def __init__(self,name):
self.name = name class Bar(object):
def __new__(cls,*agrs,**kwagrs):
return object.__new__(Foo,*agrs,**kwagrs) bar = Bar()
print(type(bar)) #foo其实是Stranger类的实例。 # 输出为:<class '__main__.Foo'>

   会发现上例:制造的是Foo的实例对象。

  总结:因此可以这么描述__new__()和__ini__()的区别,在新式类中__new__()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()使其丰满。

    如果以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地。而__init__()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,__init__()负责大楼的细节设计,建造,装修使其可交付给客户。

Python类的__new__()的更多相关文章

  1. python类的__new__和__init__

    python的类,和其他语言有一点不太一样,就是,他把新建一个类和初始化一个类,分成了两个方法: __new__ __init__ 当然,想想就知道,肯定是__new__先发生,然后才是__init_ ...

  2. python中的__new__与__init__,新式类和经典类(2.x)

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...

  3. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  4. 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑

    上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...

  5. 第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解

    上节介绍了__new__()方法这个比构造方法还重要的方法的语法,本节通过案例来详细剖析__new__()方法的细节以及它与构造方法之间的关系. 一.    案例说明 本节以圆Cir类为例来说明,为了 ...

  6. python 类以及单例模式

    python 也有面向对象的思想,则一切皆对象 python 中定义一个类: class student: count = 0         books = [] def __init__(self ...

  7. Python中的__new__和__init__

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

  8. 类和对象的创建过程(元类,__new__,__init__,__call__)

    一. type() 1.创建类的两种方式 方式一 class MyClass(object): def func(self,name): print(name) myc = MyClass() pri ...

  9. python类:magic魔术方法

    http://blog.csdn.net/pipisorry/article/details/50708812 魔术方法是面向对象Python语言中的一切.它们是你可以自定义并添加"魔法&q ...

随机推荐

  1. Jackson的基本用法与拓展

    目录 一.先搞两个测试需要使用的类 二.简单操作:obj与json互转 2.1.对象转json字符串 2.2.json字符串转对象 三.拓展需求 3.1.对象转json时,忽略某个字段 3.2.对象转 ...

  2. Ajax验证

    import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactor ...

  3. OpenShift 4.2 离线安装补充记录

    OpenShift4.2详细安装参考同事王征的安装手册(感谢王征大师的研究和答疑解惑, 大坑文章都已经搞定了,我这里是一些小坑) https://github.com/wangzheng422/doc ...

  4. EF Core使用遇到的问题

    目录 EF Core速度问题 问题描述 EF使用方法1,每一行存储一次(400条/s) EF使用方法2,链接不释放 (40条/s) EF使用方法3,多次add,一次SaveChanges(400条/s ...

  5. Windows10 下安装 oracle 客户端,安装 plsql 破解并实现汉化

    一,软件准备 1,win10 操作系统 2,oracle_11g_r2 client 这里是 64 位的软件  3, plsql 11.0.6 这里我们下载 64 的,32 位操作系统现在已经很少了, ...

  6. UE4 常用数学

    转自:https://dawnarc.com/2016/07/mathlinear-algebra%E5%90%91%E9%87%8F%E7%A7%AF%E5%A4%96%E7%A7%AF%E5%8F ...

  7. 最新超简单解读torchvision

    torchvision https://pytorch.org/docs/stable/torchvision/index.html#module-torchvision The torchvisio ...

  8. [转帖]NSA武器库知识整理

    NSA武器库知识整理 https://www.cnblogs.com/FrostDeng/p/7120812.html 美国国家安全局(NSA)旗下的“方程式黑客组织”(shadow brokers) ...

  9. Spring计时器StopWatch使用

    我们可以利用已有的工具类中的秒表,常见的秒表工具类有org.springframework.util.StopWatch.org.apache.commons.lang.time.StopWatch以 ...

  10. [NOIP2016]天天爱跑步-题解

    题面传送门 解答 设第\(j\)号玩家在\(V_j\)时刻出发. 弱化问题:如果树退化成了一条链.则在\(j\)处的观察员能观察到的\(i\)号玩家当且仅当 \[ i玩家经过j,且 \begin{ca ...