Python內置函數super的不便之處

先看示例代碼:

class Top(object):
    def foo(self):
        print('Top')

class Middle(Top):
    def foo(self):
        print('Middle')
        super(self.__class__, self).foo()

class Bottom(Middle):
    pass

b = Bottom()

繼續執行時如下這行代碼時:

 

b.foo()

報RuntimeError: maximum recursion depth exceeded while calling a Python object。

看來是由於遞歸的關係導致Python棧溢出了(CPython的函數棧很淺,使用遞歸要小心)。通過traceback信息和debug日誌知道,根本原因是Middle.foo被遞歸執行了,爲什麼會出現這樣的錯誤呢?這段代碼很普通嘛,只是最底層的子類想要使用中間父類的方法而已,這種場景太常見了,答案在super的機制上,super(type, object).method()會以實例object調用類型type的父類所定義的方法method。

b.foo()的方法查找順序是:

1、查找實例本身

2、實例的類

3、父類Middle

執行到父類的foo處,此時代碼中的self所指代的實例是Bottom的實例,self.__class__是Bottom,杯具就在這裏了,super(self.__class__, self).foo()會反覆的調用Middle.foo……

要解決這個問題很簡單,老老實實用super沒出現前的寫法即可:

 

class Middle(Top):
    def foo(self):
        print('Middle')
        Top.foo(self)

如此調用目標就很明確了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章