Python类的__new__()
本篇主要想要详细的介绍一下关于类的魔法方法__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 是当前正在实例化的类。
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__ ()方法中接收的位置参数和命名参数。
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__()使其丰满。
Python类的__new__()的更多相关文章
- python类的__new__和__init__
python的类,和其他语言有一点不太一样,就是,他把新建一个类和初始化一个类,分成了两个方法: __new__ __init__ 当然,想想就知道,肯定是__new__先发生,然后才是__init_ ...
- python中的__new__与__init__,新式类和经典类(2.x)
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)
content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...
- 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑
上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...
- 第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解
上节介绍了__new__()方法这个比构造方法还重要的方法的语法,本节通过案例来详细剖析__new__()方法的细节以及它与构造方法之间的关系. 一. 案例说明 本节以圆Cir类为例来说明,为了 ...
- python 类以及单例模式
python 也有面向对象的思想,则一切皆对象 python 中定义一个类: class student: count = 0 books = [] def __init__(self ...
- Python中的__new__和__init__
Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...
- 类和对象的创建过程(元类,__new__,__init__,__call__)
一. type() 1.创建类的两种方式 方式一 class MyClass(object): def func(self,name): print(name) myc = MyClass() pri ...
- python类:magic魔术方法
http://blog.csdn.net/pipisorry/article/details/50708812 魔术方法是面向对象Python语言中的一切.它们是你可以自定义并添加"魔法&q ...
随机推荐
- Ubuntu下配置Window CIFS共享
转自:https://blog.csdn.net/wanfengzhong/article/details/52550074 1. 准备windows共享文件夹 2. 安装 cifs-utilssud ...
- bat/cmd批处理程序设计教程
序言 这是一篇技术教程,我真心诚意会用很简单的文字表达清楚自己的意思,只要你识字就能看懂,就能学到知识.我写这篇教程的目的,是让每一个看过这些文字的朋友记住一句话:如果爱可以让事情变的更简单,那么就让 ...
- Anaconda + PyCharm + Pytorch
Anaconda 1. 下载Anaconda https://www.anaconda.com/download/ 2. 安装 3. 添加环境变量 Path - C:\Users\Godzilla ...
- 【设计】Facebook的语调设计-做的珍惜
http://www.woshipm.com/pd/3206743.html 做的是真细呦
- vue脚手架中使用Vant,实现自动按需引入组件,并将px转换为rem
偶然间看到一款不错的移动端vue组件库Vant,照着官方文档敲了一下,感觉还是不错的.想着以后的项目中可能会运用到,特此记录下,方便之后使用. 现在很多的组件库为了减小代码包体积,都支持按需加载了.V ...
- python进阶---列表、字典、集合相关操作
基本概念 列表 序列是python中一个基本的数据结构,每个元素都有一个索引index 操作 # 创建列表 list = [] # 修改列表 list[2] = 2001 # 删除列表 del lis ...
- 使用vue搭建应用四引入axios
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中 特性 从浏览器中创建 XMLHttpRequests 从 node.js 创建 http 请求 支持 P ...
- csu 1978: LXX的图论题
1978: LXX的图论题 Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 71 ...
- Re库入门
1. 正则表达式语法由字符和操作符构成 . 表示任何单个字符 [] 字符集,对单个字符给出取值范围 [abc]表示a.b.c,[a - z]表示a到z单个字符 [^] 非字符集,对单个字符给出排除 ...
- sed取某域名对应的IP