<abbr id="ciwa6"><option id="ciwa6"></option></abbr>
  • <sup id="ciwa6"><kbd id="ciwa6"></kbd></sup>
    <small id="ciwa6"></small>
  • 千鋒教育-做有情懷、有良心、有品質的職業教育機構

    400-811-9990
    手機站
    千鋒教育

    千鋒學習站 | 隨時隨地免費學

    千鋒教育

    掃一掃進入千鋒手機站

    領取全套視頻
    千鋒教育

    關注千鋒學習站小程序
    隨時隨地免費學習課程

    上海
    • 北京
    • 鄭州
    • 武漢
    • 成都
    • 西安
    • 沈陽
    • 廣州
    • 南京
    • 深圳
    • 大連
    • 青島
    • 杭州
    • 重慶
    當前位置:成都千鋒IT培訓  >  技術干貨  >  Python對象的方法調用時發生了什么?

    Python對象的方法調用時發生了什么?

    來源:千鋒教育
    發布人:xqq
    時間: 2023-10-17 14:10:23

    一、Python對象的方法調用時發生了什么

    1.尋找Eat

    catObj尋找一個叫Eat的東西,這東西可能是任意對象,名字就叫Eat(暫且先忘了Cat類里定義了什么),這其實就涉及到Python屬性訪問順序了:

    __getattribute__數據描述符對象屬性類屬性非數據描述符父類屬性__getattr__()

    為了更簡單得去理解,本文只關注對象屬性,類屬性,父類屬性這三點。

    首先從對象屬性去找:

    catObj對象有沒有名為Eat這個屬性?從上面定義的Cat類看顯然是沒有,這個對象只有一個屬性name,可打印__dict__查看對象的屬性。

    print(catObj.__dict__)

    # 打印結果:

    # {‘name’: ‘Godeng’}

    catObj.food = “Fish”

    # 打印結果:

    # {‘name’: ‘Godeng’, ‘food’: ‘Fish’}

    對象添加一個屬性,它就會進對象的__dict__里,歸根結底都是字典訪問。

    對象屬性找不到,去類屬性找,從catObj對象的__class__屬性即可索引到類:

    Cat類有沒有名為Eat這個屬性?從上面定義的Cat類看,顯然是有的,且類也是對象,也可通過打印__dict__觀察它的屬性。

    print(Cat.__dict__)

    # 打印結果:

    # {…’Eat’: ,

    # ‘__init__’: …}

    Eat和__init__赫然在列,而且Eat和__init__是一個質樸得不能再質樸的函數,函數,函數。

    如果在類屬性找不到的話,就會嘗試去父類屬性尋找,相似的過程。

    那么到此,尋找到了一個名為Eat的函數。

    2.包裝成Eat方法&調用

    def Eat(self):

    ??? print(“Cat is eating”)

    從catObj對象一路尋找到的Eat函數是長這樣的,但它并非最終的返回的方法。將函數與對象進行包裝后的產物,才是方法。

    class Method(object):

    ??? def __init__(self, obj, func):

    ?????? self.__self__ = obj

    ?????? self.__func__ = func

    ??? def __call__(self, *args, **kwargs):

    ?????? self.__func__(self.__self__, *args, **kwargs)

    catObj = Cat(“Godeng”)

    eatMethod = Method(catObj, Cat.Eat)

    eatMethod()

    上面是模擬方法的結構和大致產生調用過程,方法對象自身會引用Cat類函數Eat,和eatObj對象,并方法對象被調用時(__call__調用時),自動把eatObj對象作為了該函數的self參數。

    并非方法本身蘊含了什么不可告人的魔力,catObj.eat獲取的其實就是類似上例的Method對象,從使用形式來看它提供的一個顯著特點是,他就像一個不需要傳self參數的函數。

    方法&類函數引用上的區別:

    類函數Cat.Eat是一個普通函數對象,它被Cat類引用。

    catObj.Eat是一個方法對象,它引用了類函數Cat.Eat和catObj對象,它并不是像類函數那樣有被Cat類或catObj對象引用的一個恒久的對象,每次catObj.Eat的調用都會走一遍上述流程,產生一個新的方法對象返回。

    # 生成了一個新的方法對象,這句執行完畢后方法對象會被銷毀

    catObj.Eat()

    # 生成了一個新的方法對象, 并由eatMethod引用,方法對象不會被銷毀

    eatMethod = catObj.Eat

    # 刪除eatMethod的引用,方法對象隨之被銷毀

    eatMethod = None

    延伸閱讀:

    二、如何從父類們找類函數

    Python是門多繼承語言,在上面catObj尋找Eat到它的類的時候,如果Cat類沒有定義Eat,會嘗試向父類尋找Eat。

    class Monster(object):

    ??? def Eat(self):

    ?????? print(“Monster Eat”)

    class Pet(object):

    ??? def Eat(self):

    ?????? print(“Pet Eat”)

    class Cat(Pet, Monster):

    ??? def __init__(self, name):

    ?????? self.name = name

    假如Cat沒定義Eat,它的兩個父類Pet和Monster的都定義了Eat,那就是先在哪個父類找到Eat,那么就返回哪個父類的Eat,也即是取決于先從Pet類找,還是先從Monster類找。

    這就涉及到Python一個老生常談的概念,方法解析順序(mro),它確定了這個順序,它的具體規則會隨著Python版本迭代而迭代,如Py2是深度優先和Py3是廣度優先,具體在此就不展開了。

    可通過打印類的mro來觀察類的執行順序。

    print(Cat.mro())

    print(Cat.Eat)

    # 打印結果:

    # [, , , ]

    #

    聲明:本站稿件版權均屬千鋒教育所有,未經許可不得擅自轉載。

    猜你喜歡LIKE

    sql server2012r2所在服務器做端口限制,需要開放什么端口才能繼續訪問數據庫?

    2023-10-17

    Oracle有什么優勢和劣勢?

    2023-10-17

    CSS 隱藏頁面元素有哪些方法?

    2023-10-17

    最新文章NEW

    數據庫聚集索引非聚集索引實現上有哪些區別?

    2023-10-17

    開發web應用,好的開發流程是怎么樣的?

    2023-10-17

    為什么說Gradle是Android進階繞不去的坎?

    2023-10-17

    相關推薦HOT

    更多>>

    快速通道 更多>>

    最新開班信息 更多>>

    網友熱搜 更多>>