91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2020-09-09 15:09:55 來源:億速云 閱讀:215 作者:小新 欄目:編程語言

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

我們在使用python中的類繼承時,子類繼承父類后,在重載父類的方法后,在方法中如果要執行父類對應的方法,一般有兩種方式: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類中,有一個move方法用來移動位置,在子類中我們想要增加一個記錄,記住每次移動的偏移量,那么我們就在子類中重載move函數,執行我們自定義的操作(記錄偏移量),然后繼續執行父類的move動作,直接調用父類move函數就可以避免我們重新實現移動位置的動作。

在上面的例子中,我們使用了super來調用父類方法,那么能不能使用Base來調用呢?

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

可以看到Base調用父類函數時,必須在函數中傳遞self參數。之前的文章中我們了解到類的普通函數調用需要使用類對象調用,而類的普通函數第一個參數默認是self,調用時不需要傳遞此參數,因為通過對象調用會自動傳遞。但是直接使用Base類名調用時,方法內部需要知道self是誰。那么兩種方式都可以,他們有區別嗎?當然是有的

首先看一下super的定義

class super(object):
    """
    super() -> same as super(__class__, <first argument>)
    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有四種調用方式

super(): 相當于super(當前類名, 第一個參數)      python3中新增的方式

super(type):沒有綁定對象

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

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

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

在上面的例子中我們看到super和Base的方式一樣,接下來我們再看一個例子

# -*- 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

四個類,Base初始化函數被調用了兩次,為什么呢?Sub.__init__中Device1和Device2都調用了初始化方法,是這個原因嗎?準確點來講,是的,可不可以只調用一個,那么Base就只會被調用一次嘍,如果只調用Device1.__init__會有什么結果?

Base
Device1
Sub
Traceback (most recent call last):
  File "/Users/small_bud/Desktop/Python/SpiderProjects/淘寶搜索/__init__.py", line 30, in <module>
    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'

沒有name2屬性,而且Device2的初始化函數__init__沒有調用,所以name2屬性沒有被定義,那如果把Base換成super,結果怎么樣呢?

# -*- 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

我們類的每一個函數首地址會被存儲起來,當我們用類名去調用一個函數的時候,我們可以理解為它代表一個絕對的地址,可以絕對定位到函數的地址。這個時候你可以把它理解為一個普通函數def Base.__init__(self),函數名是Base.__init__,參數是self

# 這是一個測試類,只為創建一個空對象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是一樣的,這絕不是我們所希望的類函數。那么為什么super會正確的找到要執行的函數呢?看一下下面的例子:

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
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

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

子類會先于父類被檢查

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

多個父類會根據它們在列表中的順序被檢查

C繼承自A、B,A和B哪個先被調用,根據他們在表中的順序

如果對下一個類存在兩個合法的選擇,選擇第一個父類

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

以上是Python中super().__init__和Base.__init__的區別是什么的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

集贤县| 乃东县| 广河县| 饶平县| 大安市| 昆明市| 潜江市| 威远县| 新丰县| 洞头县| 木兰县| 达拉特旗| 清徐县| 麦盖提县| 德令哈市| 拉萨市| 昌吉市| 清新县| 容城县| 喜德县| 庆元县| 千阳县| 建湖县| 宜君县| 曲阳县| 东山县| 酉阳| 平潭县| 剑川县| 张北县| 龙胜| 莫力| 江油市| 威远县| 应城市| 荔波县| 双柏县| 都匀市| 兰考县| 洪江市| 临沂市|