p3新式类__new__使用和实例化
是真正在内存中分配的内存地址
示例1·
class Foo(object):
# __metaclass__ = MyType def __init__(self, name):
self.name = name def __new__(cls, *args, **kwargs):
return object.__new__(cls) obj1 = Foo('123aaa')
print(obj1) 示例二:
class S:
print(111) class Foo(object):
# __metaclass__ = MyType def __init__(self, name):
self.name = name def __new__(cls, *args, **kwargs):
return object.__new__(S) obj1 = Foo('123aaa')
print(obj1)
new()是在新式类中新出现的方法,它作用在构造方法init()建造实例之前,可以这么理解,在Python 中存在于类里面的构造方法init()负责将类的实例化,而在init()调用之前,new()决定是否要使用该init()方法,因为new()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。
如果将类比喻为工厂,那么init()方法则是该工厂的生产工人,init()方法接受的初始化参 数则是生产所需原料,init()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而 new()则是生产部经理,new()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出 货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。
new()方法的特性:
new()方法是在类准备将自身实例化时调用。
new()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。
类的实例化和它的构造方法通常都是这个样子:
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)
# return Stranger.__new__(cls, *args, **kwargs)
# return Child.__new__(cls, *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)。
使用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()负责大楼的细节设计,建造,装修使其可交付给客户
p3新式类__new__使用和实例化的更多相关文章
- 新式类__new__()方法
概述 __new__() 是在新式类中新出现的方法,在 Python 中类实例化时,__new__()方法用在 __init__() 启动之前,决定是否要使用该 __init__() 方法,因为__n ...
- python中的__new__与__init__,新式类和经典类(2.x)
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- python2中的__new__与__init__,新式类和经典类-乾颐堂
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- [Python] Python 之 __new__() 方法与实例化
__new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() ...
- Python 之 __new__() 方法与实例化
原文链接:https://www.cnblogs.com/ifantastic/p/3175735.html __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解, ...
- Python中的__new__()方法与实例化
@Python中的__new__()方法与实例化 __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...
- Python 之 __new__() 方法与实例化(转)
_new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() ...
- python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。
单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样. 如下: 源码: class A(object): d ...
- python开发学习-day07(面向对象之多态、类的方法、反射、新式类and旧式类、socket编程)
s12-20160227-day07 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
随机推荐
- Observer(观察者)
意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新. 适用性: 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面.将这二者封装在独立 ...
- 【Docker】Windows下docker环境搭建及解决使用非官方终端时的连接问题
背景 时常有容器方面的需求,经常构建调试导致测试环境有些混乱,所以想在本地构建一套环境,镜像调试稳定后再放到测试环境中. Windows Docker 安装 安装docker toolbox 博主的电 ...
- 【Python】模块学习之matplotlib柱状图、饼状图、动态图及解决中文显示问题
前言 众所周知,通过数据绘图,我们可以将枯燥的数字转换成容易被人们接受的图表,从而让人留下更加深刻的印象.而大多数编程语言都有自己的绘图工具,matplotlib就是基于Python的绘图工具包,使用 ...
- IDEAL葵花宝典:java代码开发规范插件 GenerateAllSetter、ECtranslation、translation、插件
前言: GenerateAllSetter: 我们在程序开发过程中,往往要编写这样的类:类的部分或者全部属性不希望让外部世界直接访问,而不用public字段修饰.这样,方法调用成了访问这些属性的唯一 ...
- Java线程状态分析
Java线程的生命周期中,存在几种状态.在Thread类里有一个枚举类型State,定义了线程的几种状态,分别有: NEW: 线程创建之后,但是还没有启动(not yet started).这时候它的 ...
- windows 下搭建python虚拟环境
###################################windows 下测试环境 C:\Users\wongg\django-cmdb>cd ..\cmdb ##下载get-pi ...
- Linux 的 Out-of-Memory (OOM) Killer
同事在 Linux 服务器上遇到点小问题,我也上去折腾半天.这还是第一次注意到 Linux 这个多年来就存在的特性:OOM Killer .说白了 OOM Killer 就是一层保护机制,用于避免 L ...
- STL标准库-容器-map和multimap
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 map与multimap为关联容器,结构如下 map底层实现依然是rb_tree 他的data可以改,但是key不能改,因此ma ...
- 面试题总结(一)、TCP协议
声明:本文主要探讨当TCP协议出现在面试笔试场合可能会涉及的问题,每一个知识点讨论力求简洁,便于记忆,但讨论深度有限,如要深入研究可点击参考链接,希望对正在找工作的同学有点帮助. 一.TCP协议简介 ...
- MySQL数据引擎InnoDB和MyISAM互相转换
MySQL(或者社区开源fork的MariaDB)5.5以上支持InnoDB引擎,并将其作为默认数据库引擎.InnoDB带来很多改进,但是对系统资源占用明显增加,对于还在128MB-512MB内存VP ...