真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python中super().__init__和Base.__init__的區(qū)別是什么

小編給大家分享一下Python中super().__init__和Base.__init__的區(qū)別是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

德令哈網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)建站自2013年起到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)建站。

我們?cè)谑褂胮ython中的類繼承時(shí),子類繼承父類后,在重載父類的方法后,在方法中如果要執(zhí)行父類對(duì)應(yīng)的方法,一般有兩種方式:super和Base(表示父類名)。

使用例子

先看下面一段代碼:

# -*- coding: utf-8 -*-class Base:
    def __init__(self):
        self.postion = (0, 0)    def move(self, x, y):
        self.postion = (self.postion[0] + x, self.postion[1] + y)class Device(Base):
    def __init__(self):
        super(Device, self).__init__()
        self.offset = (0, 0)    # 記錄本次位置偏移量
    def move(self, x, y):
        self.offset = (self.postion[0] - x, self.postion[1] - y)
        super(Device, self).move(x, y)        
    def get_offset(self):
        return self.offset

在Base類中,有一個(gè)move方法用來(lái)移動(dòng)位置,在子類中我們想要增加一個(gè)記錄,記住每次移動(dòng)的偏移量,那么我們就在子類中重載move函數(shù),執(zhí)行我們自定義的操作(記錄偏移量),然后繼續(xù)執(zhí)行父類的move動(dòng)作,直接調(diào)用父類move函數(shù)就可以避免我們重新實(shí)現(xiàn)移動(dòng)位置的動(dòng)作。

在上面的例子中,我們使用了super來(lái)調(diào)用父類方法,那么能不能使用Base來(lái)調(diào)用呢?

....
Base.__init__(self)
......
Base.move(self, x, y)
....

可以看到Base調(diào)用父類函數(shù)時(shí),必須在函數(shù)中傳遞self參數(shù)。之前的文章中我們了解到類的普通函數(shù)調(diào)用需要使用類對(duì)象調(diào)用,而類的普通函數(shù)第一個(gè)參數(shù)默認(rèn)是self,調(diào)用時(shí)不需要傳遞此參數(shù),因?yàn)橥ㄟ^(guò)對(duì)象調(diào)用會(huì)自動(dòng)傳遞。但是直接使用Base類名調(diào)用時(shí),方法內(nèi)部需要知道self是誰(shuí)。那么兩種方式都可以,他們有區(qū)別嗎?當(dāng)然是有的

首先看一下super的定義

class super(object):
    """
    super() -> same as super(__class__, )
    super(type) -> unbound super object
    super(type, obj) -> bound super object; requires isinstance(obj, type)
    super(type, type2) -> bound super object; requires issubclass(type2, type)
    Typical use to call a cooperative superclass method:
    class C(B):
        def meth(self, arg):
            super().meth(arg)
    This works for class methods too:
    class C(B):
        @classmethod
        def cmeth(cls, arg):
            super().cmeth(arg)
    """

可以看到,super有四種調(diào)用方式

super(): 相當(dāng)于super(當(dāng)前類名, 第一個(gè)參數(shù))      python3中新增的方式

super(type):沒(méi)有綁定對(duì)象

super(type, obj):綁定對(duì)象,要求obj的類型是type或者其子類

super(type, type2):綁定對(duì)象,要求type2是type的子類

這里我們就先說(shuō)一下super()和super(type, obj),這是我們常用的方式

在上面的例子中我們看到super和Base的方式一樣,接下來(lái)我們?cè)倏匆粋€(gè)例子

# -*- coding: utf-8 -*-class Base:
    def __init__(self):
        print("Base")
        self.name = "Base"class Device1(Base):
    def __init__(self):
        Base.__init__(self)
        print("Device1")
        self.name1 = "Device1"class Device2(Base):
    def __init__(self):
        Base.__init__(self)
        print("Device2")
        self.name2 = "Device2"class Sub(Device1, Device2):
    def __init__(self):
        Device1.__init__(self)
        Device2.__init__(self)
        print("Sub")
        self.name3 = "Sub"

    def test(self):
        print("test: ", self.name2)

s = Sub()
s.test()# 輸出:Base                #Base.__init__中的printDevice1           
#Device1.__init__中的printBase                #Base.__init__中的printDevice2           
#Device2.__init__中的printSub                  #Sub.__init__中的printtest:  Device2  #test方法中的print

四個(gè)類,Base初始化函數(shù)被調(diào)用了兩次,為什么呢?Sub.__init__中Device1和Device2都調(diào)用了初始化方法,是這個(gè)原因嗎?準(zhǔn)確點(diǎn)來(lái)講,是的,可不可以只調(diào)用一個(gè),那么Base就只會(huì)被調(diào)用一次嘍,如果只調(diào)用Device1.__init__會(huì)有什么結(jié)果?

Base
Device1
Sub
Traceback (most recent call last):
  File "/Users/small_bud/Desktop/Python/SpiderProjects/淘寶搜索/__init__.py", line 30, in 
    s.test()
  File "/Users/small_bud/Desktop/Python/SpiderProjects/淘寶搜索/__init__.py", line 27, in test
    print("test: ", self.name2)
AttributeError: 'Sub' object has no attribute 'name2'

沒(méi)有name2屬性,而且Device2的初始化函數(shù)__init__沒(méi)有調(diào)用,所以name2屬性沒(méi)有被定義,那如果把Base換成super,結(jié)果怎么樣呢?

# -*- coding: utf-8 -*-class Base:
    def __init__(self):
        print("Base")
        self.name = "Base"class Device1(Base):
    def __init__(self):
        super().__init__()
        print("Device1")
        self.name1 = "Device1"class Device2(Base):
    def __init__(self):
        super().__init__()
        print("Device2")
        self.name2 = "Device2"class Sub(Device1, Device2):
    def __init__(self):
        super().__init__()
        print("Sub")
        self.name3 = "Sub"

    def test(self):
        print("test: ", self.name2)

s = Sub()
s.test()# 輸出:Base               #Base.__init__中的printDevice2           
#Device2.__init__中的printDevice1           #Device2.__init__中的printSub                  
#Sub.__init__中的printtest:  Device2   #test方法中的print

我們類的每一個(gè)函數(shù)首地址會(huì)被存儲(chǔ)起來(lái),當(dāng)我們用類名去調(diào)用一個(gè)函數(shù)的時(shí)候,我們可以理解為它代表一個(gè)絕對(duì)的地址,可以絕對(duì)定位到函數(shù)的地址。這個(gè)時(shí)候你可以把它理解為一個(gè)普通函數(shù)def Base.__init__(self),函數(shù)名是Base.__init__,參數(shù)是self

# 這是一個(gè)測(cè)試類,只為創(chuàng)建一個(gè)空對(duì)象class Test:
    passclass Base:
    def __init__(self):
        self.name = "aaaa"def func(obj):
    obj.age = 111t = Test()
Base.__init__(t)
print(t.name)
func(t)
print(t.age)#輸出:aaaa111

看到了,Base.__init__和func是一樣的,這絕不是我們所希望的類函數(shù)。那么為什么super會(huì)正確的找到要執(zhí)行的函數(shù)呢?看一下下面的例子:

class A:
    def __init__(self):
        print("A")class B:
    def __init__(self):
        super().__init__()
        print("B")class C(B, A):
    def __init__(self):
        super().__init__()
        print("C")class D(C):
    def __init__(self):
        super().__init__()
        print("D")

D()
print(D.mro())#輸出:A
B
C
D
[]

我們知道子類的對(duì)象初始化時(shí),將先執(zhí)行父類的初始化,然后才執(zhí)行子類初始化,從初始化打印信息也可以看出來(lái),A>B>C>D,再看一下mro()函數(shù)的打印信息,這里展示了當(dāng)前類及其父類的類名,我們可以這樣理解每一個(gè)類被定義后,其存儲(chǔ)在程序存儲(chǔ)區(qū),除了類方法,還存在一個(gè)繼承管理表,表中按照一定的順序存儲(chǔ)著類及其父類的類名,類的初始化就按照表中的順序進(jìn)行初始化,按照以上的順序object>A>B>C>D,從object開(kāi)始初始化,然后是A、B、C、D。之前Base.__init__的調(diào)用我們分析過(guò)了,現(xiàn)在super這種方式呢?它是根據(jù)mro列表中記錄的類,按照順序依次調(diào)用,這樣就不會(huì)出現(xiàn)一個(gè)類被重復(fù)調(diào)用的情況。MRO列表是通過(guò)一種算法計(jì)算出順序的,我們不用關(guān)注它,不過(guò)要記住以下幾個(gè)準(zhǔn)則:

子類會(huì)先于父類被檢查

子類一定是在列表的第一位

多個(gè)父類會(huì)根據(jù)它們?cè)诹斜碇械捻樞虮粰z查

C繼承自A、B,A和B哪個(gè)先被調(diào)用,根據(jù)他們?cè)诒碇械捻樞?/p>

如果對(duì)下一個(gè)類存在兩個(gè)合法的選擇,選擇第一個(gè)父類

通過(guò)上面的分析,我們知道在類繼承中,一定要使用super的方式才能正確調(diào)用類繼承關(guān)系,在python3中推薦使用super().__init__,pytho2中使用super(Base, self).__init__。

以上是Python中super().__init__和Base.__init__的區(qū)別是什么的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


網(wǎng)站標(biāo)題:Python中super().__init__和Base.__init__的區(qū)別是什么
文章路徑:http://weahome.cn/article/peddsi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部