久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

python中__init__()方法和__new__()方法的區(qū)別

 legionDataLib 2017-12-29
轉(zhuǎn)載于:http://blog.csdn.net/four_infinite/article/details/52806594
__new__()是新式類中才出現(xiàn)的方法,即只有從object繼承的類才有該方法。注意,,新式類是從python2.2開(kāi)始加入的,,在python2.x中同時(shí)存在新式類和舊式類(舊式類也稱經(jīng)典類,主要是為了兼容以前的代碼),但是在python3.x中已經(jīng)完全摒棄舊式類了,在python3.x中即使不顯示的寫(xiě)明從object繼承,系統(tǒng)也會(huì)默認(rèn)從object繼承,。

在舊式類中,實(shí)例的構(gòu)造只調(diào)用__init__()這一個(gè)函數(shù)(至少?gòu)耐獗韥?lái)看是如此),,因此很多場(chǎng)合稱__init__()為構(gòu)造函數(shù),,在舊式類中這完全沒(méi)問(wèn)題,但是在新式類中這么叫并不完全合適,。

在新式類中,,實(shí)例的構(gòu)造先調(diào)用__new__()函數(shù)返回一個(gè)實(shí)例,然后調(diào)用__init__()對(duì)返回的實(shí)例進(jìn)行初始化,。因此可以看出__new__()才是真正的構(gòu)造函數(shù),,__init__()只是起到了初始化的過(guò)程。

1:__new__()與__init__()的調(diào)用順序
#!/usr/bin/env python

class A(object):
    def __init__(self,*args,**kwargs):
        print "init &&&&  %s" % self.__class__
    def __new__(cls,*args,**kwargs):
        print "new &&&&  %s" % cls
        return object.__new__(cls,*args,**kwargs)

a=A()
輸出結(jié)果為:
new &&&&  <class '__main__.A'>
init &&&&  <class '__main__.A'>

如果把最后一行的return代碼屏蔽掉,,輸出結(jié)果為:
new &&&&<class '__main__.A'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

一般來(lái)說(shuō),,”init”和”new”函數(shù)都會(huì)有下面的形式:

def __init__(self, *args, **kwargs):
    # func_suite

def __new__(cls, *args, **kwargs):
    # func_suite
  • 1
  • 2
  • 3
  • 4
  • 5

對(duì)于”new”和”init”可以概括為: 
new”方法在Python中是真正的構(gòu)造方法(創(chuàng)建并返回實(shí)例),通過(guò)這個(gè)方法可以產(chǎn)生一個(gè)”cls”對(duì)應(yīng)的實(shí)例對(duì)象,,所以說(shuō)”new”方法一定要有返回,。 
對(duì)于”init”方法,是一個(gè)初始化的方法,,”self”代表由類產(chǎn)生出來(lái)的實(shí)例對(duì)象,,”init”將對(duì)這個(gè)對(duì)象進(jìn)行相應(yīng)的初始化操作。

重寫(xiě)_new_ 
如果(新式)類中沒(méi)有重寫(xiě)”new”方法,,Python默認(rèn)是調(diào)用該類的直接父類的”new”方法來(lái)構(gòu)造該類的實(shí)例,,如果該類的父類也沒(méi)有重寫(xiě)”new”,那么將一直按照同樣的規(guī)則追溯至object的”new”方法,,因?yàn)閛bject是所有新式類的基類,。

而如果新式類中重寫(xiě)了”new”方法,那么可以選擇任意一個(gè)其他的新式類(必須是新式類,,只有新式類有”new”,,因?yàn)樗行率筋惗际菑膐bject派生)的”new”方法來(lái)創(chuàng)建實(shí)例,包括這個(gè)新式類的所有前代類和后代類,只要它們不會(huì)造成遞歸死循環(huán),。

看一段例子代碼:

#!/usr/bin/env python
#coding:utf-8

class Foo(object):
    def __new__(cls,*args,**kwargs):
        obj = object.__new__(cls,*args,**kwargs)
        #這里的object.__new__(cls,*args,**kwargs)等價(jià)于
        # super(Foo,cls).__new__(cls,*args,**kwargs)
        # object.__new__(Foo,*args,**kwargs)
        # Bar.__new__(cls,*args,**kwargs)
        # Student.__new__(cls,*args,**kwargs),即使Student和
        # Foo沒(méi)有關(guān)系也是允許的,,因?yàn)镾tudent是由object派生的新類
        # 在任何新式類中,不能調(diào)用自身的__new__來(lái)創(chuàng)建實(shí)例,,因?yàn)檫@會(huì)
        # 造成死循環(huán),,所以要避免出現(xiàn)這樣的語(yǔ)法 Foo.__new__(cls,*args,**kwargs)
        # 或者 cls.__new__(cls,*args,**kwargs)
        print "Calling __new__ for %s" % obj.__class__
        return obj

class Bar(Foo):
    def __new__(cls,*args,**kwargs):
        obj = object.__new__(cls,*args,**kwargs)
        print "Calling __new__ for %s" % obj.__class__
        return obj

class Student(object):
    #Student沒(méi)有__new__方法,那么會(huì)自動(dòng)調(diào)用父類的__new__方法來(lái)
    #創(chuàng)建實(shí)例,,即會(huì)自動(dòng)調(diào)用object.__new__(cls)
    pass

class Car(object):
    def __new__(cls,*args,**kwargs):
        obj = object.__new__(Bar,*args,**kwargs)
        print "Calling __new__ for %s" % obj.__class__
        return obj

foo = Foo()
bar = Bar()
car = Car()

運(yùn)行結(jié)果是:

Calling __new__ for <class '__main__.Foo'>
Calling __new__ for <class '__main__.Bar'>
Calling __new__ for <class '__main__.Bar'>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

_init_的調(diào)用

new”決定是否要使用該類的”init”方法,,因?yàn)椤?strong style="box-sizing: border-box;">new” 可以調(diào)用其他類的構(gòu)造方法或者直接返回別的類創(chuàng)建的對(duì)象來(lái)作為本類的實(shí)例。 
通常來(lái)說(shuō),,新式類開(kāi)始實(shí)例化時(shí),,”new”方法會(huì)返回cls(cls指代當(dāng)前類)的實(shí)例,,然后調(diào)用該類的”init”方法作為初始化方法,,該方法接收這個(gè)實(shí)例(即self)作為自己的第一個(gè)參數(shù),然后依次傳入”new”方法中接收的位置參數(shù)和命名參數(shù),。 
但是,,如果”new”沒(méi)有返回cls(即當(dāng)前類)的實(shí)例,那么當(dāng)前類的”init”方法是不會(huì)被調(diào)用的,??聪旅娴睦樱?/p>

#!/usr/bin/env python

class A(object):
    def __init__(self,*args,**kwargs):
        print "calling __init__ from %s" % self.__class__

    def __new__(cls,*args,**kwargs):
        obj = object.__new__(cls,*args,**kwargs)
        print "calling __new__ from %s" % obj.__class__
        return obj

class B(A):
    def __init__(self,*args,**kwargs):
        print "calling __init__ from %s" % self.__class__
    def __new__(cls,*args,**kwargs):
        obj = object.__new__(A,*args,**kwargs)
        print "calling __new__ from %s" % obj.__class__
        return obj

b=B()
print type(b)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

代碼中,在B的”new”方法中,,通過(guò)”obj = object.new(A, *args, **kwargs)”創(chuàng)建了一個(gè)A的實(shí)例,,在這種情況下,B的”init”函數(shù)就不會(huì)被調(diào)用到,。

運(yùn)行結(jié)果是:

calling __new__ from <class '__main__.A'>
<class '__main__.A'>
  • 1
  • 2

派生不可變類型

關(guān)于”new”方法還有一個(gè)重要的用途就是用來(lái)派生不可變類型 
例如,,python中的float類型是一個(gè)不可變類型,如果想要從float中派生出一個(gè)子類,,就可以使用”new”方法:

#!/usr/bin/env python

class Round2Float(float):
    def __new__(cls,num):
        num = round(num,2)
        obj = float.__new__(Round2Float,num)
        return obj

f=Round2Float(4.324599)
print f
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

這段程序從float類中派生出了一個(gè)Round2Float類,,這個(gè)類的作用就是保留小數(shù)點(diǎn)后兩位的浮點(diǎn)數(shù)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多