Python中__new__()方法的使用和实例化
  • 1
  • 2

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)
  • 1
  • 2
  • 3
  • 4
  • 5

正如以上所示,一个类可以有多个位置参数和多个命名参数,而在实例化开始之后,在调用 init()方法之前,Python首先调用new()方法:

def __new__(cls, *args, **kwargs):
...
  • 1
  • 2

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

def __new__(cls, *args, **kwargs):
...
return object.__new__(cls)
  • 1
  • 2
  • 3

事实上如果(新式)类中没有重写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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

#如果Child中没有定义new()方法,那么会自动调用其父类的new()方法来制造实例,即

Foo.__new__(cls, *args, **kwargs)
  • 1

在任何新式类的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):
...
  • 1
  • 2

在制造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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

打印的结果显示foo其实是Stranger类的实例。

因此可以这么描述new()和ini()的区别,在新式类中new()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法init()使其丰满。 
如果以建房子做比喻,new()方法负责开发地皮,打下地基,并将原料存放在工地。而init()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,init()负责大楼的细节设计,建造,装修使其可交付给客户。

Python中__new__()方法的使用和实例化
2016年10月12日 17:35:43

阅读数:8883
 本篇文章转载自网络。
  • 1
  • 2

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)
  • 1
  • 2
  • 3
  • 4
  • 5

正如以上所示,一个类可以有多个位置参数和多个命名参数,而在实例化开始之后,在调用 init()方法之前,Python首先调用new()方法:

def __new__(cls, *args, **kwargs):
...
  • 1
  • 2

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

def __new__(cls, *args, **kwargs):
...
return object.__new__(cls)
  • 1
  • 2
  • 3

事实上如果(新式)类中没有重写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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

#如果Child中没有定义new()方法,那么会自动调用其父类的new()方法来制造实例,即

Foo.__new__(cls, *args, **kwargs)
  • 1

在任何新式类的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):
...
  • 1
  • 2

在制造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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

打印的结果显示foo其实是Stranger类的实例。

因此可以这么描述new()和ini()的区别,在新式类中new()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法init()使其丰满。 
如果以建房子做比喻,new()方法负责开发地皮,打下地基,并将原料存放在工地。而init()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,init()负责大楼的细节设计,建造,装修使其可交付给客户。

__new__()方法的使用和实例化的更多相关文章

  1. Python中__new__()方法的使用和实例化

    new()是在新式类中新出现的方法,它作用在构造方法init()建造实例之前,可以这么理解,在Python 中存在于类里面的构造方法init()负责将类的实例化,而在init()调用之前,new()决 ...

  2. [Python] Python 之 __new__() 方法与实例化

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

  3. __new__方法首先调用并返回一个实例化对象

    >>> class CapStr(str): def __new__(cls,string): string = string.upper() return str.__new__( ...

  4. Python 之 __new__() 方法与实例化

    原文链接:https://www.cnblogs.com/ifantastic/p/3175735.html __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解, ...

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

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

  6. Python 之 __new__() 方法与实例化(转)

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

  7. 【python】Python 之 __new__() 方法与实例化

    本文转自:http://www.cnblogs.com/ifantastic/p/3175735.html __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 ...

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

    __new__() 是新式类中才有的方法,它执行在构造方法创建实例之前.可以这么理解,在 Python 中类中的构造方法 __init__() 负责将类实例化,而在 __init__() 启动之前,_ ...

  9. 第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解

    第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解 前面章节介绍了Python类中的__new__方法和构造方法__init__,并通过实例分析了二者之间关 ...

随机推荐

  1. github管理的建立(SSH Key生成步骤)

    Git是分布式的代码管理工具,远程的代码管理是基于SSH的,所以要使用远程的Git则需要SSH的配置. github的SSH配置如下: 一 . 设置Git的user name和email: $ git ...

  2. 2. MariaDB激活二进制日志

    翻译人员: 铁锚 翻译时间: 2013年12月25日 原文地址: Activating the Binary Log 参考了: <高可用MySQL 构建健壮的数据中心> 要启用二进制日志功 ...

  3. hadoop学习要点

    一.HDFS (一)HDFS 概念 (二)HDFS命令行接口 (三)Java 接口 (四)文件读取和文件写入,一致性 (五)集群数据的均衡 (六)存档 (七)NameNode 单点故障问题 (八)大量 ...

  4. Windows7 64位机上,OpenCV中配置CUDA,实现GPU操作步骤

    原文地址:http://blog.csdn.net/haorenka2010/article/details/24385955 按语:首先感谢http://blog.csdn.net/fengbing ...

  5. iOS开发:创建真机调试证书步骤(还有一篇是真机测试步骤)(2015年)

    (关于真机测试步骤的blog:http://blog.csdn.net/hbblzjy/article/details/51680282) 1.首先打开苹果的开发者网站(https://develop ...

  6. Windows环境下搭建React Native

    随着移动开发越来越火热,前端开发也是有之前11年一直火热到现在,不过我发现从去年年底开发,Android和ios基本已经饱和了,特别是随着广大开源社区的中很多人贡献代码,开发已经不是什么问题了,所以现 ...

  7. 推荐大家在GitHub 上值得关注学习的 iOS 开源项目

    GitHub上有很多不错的iOS开源项目,和大家特别推荐以下几个项目: 1. ReactiveCocoa GitHub链接:ReactiveCocoa/ReactiveCocoa GitHub自家的函 ...

  8. Linux下简易线程池

    线程池简介 线程池是可以用来在后台执行多个任务的线程集合. 这使主线程可以自由地异步执行其他任务.线程池通常用于服务器应用程序. 每个传入请求都将分配给线程池中的一个线程,因此可以异步处理请求,而不会 ...

  9. Android进阶(十九)AndroidAPP开发问题汇总(三)

    Android进阶(十九)AndroidAPP开发问题汇总(三) Java解析XML的几种方式: http://inotgaoshou.iteye.com/blog/1012188 从线程返回数据的两 ...

  10. 在Mac OS X下搭建gtk编译环境

    首先安装 XQuartz X11 for Mac ,可以到这里下载: http://xquartz.macosforge.org/landing/ 需要一个包管理器,我用的是brew,其他的操作类似: ...