python 中__init__与__new__的区别

图片发自简书App

旧式和新式类中的__NEW____INIT__
本文的目的是讨论Python的__new____init__方法。
newinit方法不同的行为本身之间以及旧式与新式python类定义之间。

了解__new____init__之间的区别

这两种方法的主要区别是__new__处理对象创建,而__init__处理对象初始化。
在实例化过程中,如果定义不同,这两者在工作方式上略有差异。

有关Python中的类

Classes in python are classified as new-style and old-style. Old-style classes are the ones that are prior to python 3 and defined without inheriting from base class 'object', which in turn is inherited from 'type' by default.

python 2.x中的旧式类:

class A:  # -> inherits from 'type'
    pass

python 2.x中的新式类:

class A(object):  # -> clearly inherits from 'object'
    pass

In python 3 there aren't new or old styles of classes and they inherit directly from 'object' so there is no need to specify it as a base anymore.

在本文的其余部分中,我们将介绍两种情况下的 __new____init__方法,以确定它们的行为方式以及如何使用它们。

深度讲解

Before diving into the actual implementations you need to know that new accepts cls as it's first parameter and init accepts self, because when calling new you actually don't have an instance yet, therefore no self exists at that moment, whereas init is called after new and the instance is in place, so you can use self with it.

__new____init__用于旧式类

旧式类实际上并没有__new__方法,因为对于它们来说__init__是构造函数,假设如下:

class A:
    
    def __new__(cls):
        print "A.__new__ is called"  # -> this is never called

A()

在这种情况下new 的主体将永远不会被执行,因为它不是老式类的目的。

如果我们要重写__init__

class A:

    def __init__(self):
        print "A.__init__ called"

A()

输出将是:

A.__init__ called

现在让我们尝试从__init__返回一些东西:

class A:

    def __init__(self):
        return 29

A()

这会产生:

TypeError: __init__() should return None

所以这意味着我们实际上无法控制实例化旧式类时要返回的内容。

__new____init__用于新的样式类

新风格的类让开发人员同时覆盖__new____init__,他们有不同的用途,__new__ (构造函数)仅用于创建object__init__ (初始化程序)来初始化它。

让我们看看他们的执行顺序:

class A(object):  # -> don't forget the object specified as base

    def __new__(cls):
        print "A.__new__ called"
        return super(A, cls).__new__(cls)

    def __init__(self):
        print "A.__init__ called"

A()

输出将是:

A.__new__ called
A.__init__ called

您可能想知道__init____new__在哪里被调用,而我为您准备的是__new__在调用类名(实例化时)时自动调用,而__init____new__每次由__new__返回时被调用,而将实例返回传递给__init__self'作为参数,因此,即使您将该实例保存在全局/静态的某个位置,并且每次先都从__new__返回,每次都会调用__init__

知道了这一点就意味着如果我们调用super__new__,那么__init__将不会被执行。让我们来看看是不是这样的情况:

class A(object):

    def __new__(cls):
        print "A.__new__ called"

    def __init__(self):
        print "A.__init__ called"  # -> is actually never called

print A()

输出是:

A.__new__ called
None

显然,实例被识别为None,因为我们不从构造函数返回任何东西。

想知道如果我们从__new__返回什么可能会发生什么?

笑脸

猜猜输出是什么:

class A(object):

    def __new__(cls):
        print "A.__new__ called"
        return 29

print A()

让我们看看当我们从__init__返回时会发生什么:

A.__new__ called
29

这产生:

class A(object):

    def __init__(self):
        print "A.__init__ called" 
            return 33  # -> TypeError: __init__ should return None

A()

这主要是因为调用__init__的处理程序 引发了TypeError异常,并且从__init__返回任何内容都没有意义,因为它的目的只是改变新创建的实例的新状态。


看起来新型的类在灵活性方面有提高,允许我们在创建和初始化级别执行任何PRE / POST操作,并使我们控制在实例化时返回的内容。
考虑到这一点,我们试着返回一个不同类的实例。

首先我们定义一个类:

class Sample(object):
    
    def __str__(self):
        return "SAMPLE"

然后我们定义__new__覆盖类:

class A(object):

    def __new__(cls):
        return Sample()

这也可以写成:

class A(object):

    def __new__(cls):
        return super(A, cls).__new__(Sample)

然后调用:

print A()

那会输出:

SAMPLE

这里是我写的一个例子,帮助大家理解:

class Alfa(object):
    def __new__(cls):
        #creat a generate ,get int value by filter
        #g=(x for x in range(10) if isinstance(x,int) and x <0)
        print("__new__")
        #return an parent instance 
        return super().__new__(cls)
    def __init__(self):
        print ("__init__")
        print (id(self))#print self address at Memory
        super().__init__()
#l=['a',1,2,-2,-5,8,9,0]
t=Alfa()# instantiation a object
print(id(t))#print self address at Memory
print(t)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • Python 面向对象Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对...
    顺毛阅读 4,211评论 4 16
  • 摘要 本文讨论了Python中__init__和__new__方法。 __new__和__init__具有不同的功...
    耀凯考前突击大师阅读 8,160评论 7 22
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,598评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,629评论 18 139
  • 今天下班有点晚了,就跟木木商量去学校吃饭,也能增加些美好的回忆。学校刚刚开学,食堂相比较前不久丰满了不少,学弟学妹...
    娜兰阅读 301评论 0 0