Sympy的一個Bug,牽涉到Python多重繼承問題
Sympy(gometry子包)中發現的一個bug
- 問題來源:獲取點到線段的距離。
- 點到線段的距離與點到直線的距離不同,點到線段的最短距離並不一定是垂直距離。但是當使用sympy.geometry.line中的Segmnet類建立例項化的線段,並使用Segment類中的 distance() 方法獲取 某個點到這條線段的距離時,發現無論點在何處,計算的始終是點到直線的距離(即垂直距離)。
p1_sym = sympy.geometry.point.Point(1, 0)
p2_sym = sympy.geometry.point.Point(0, 1)
p3_sym = sympy.geometry.point.Point(10, 0)
s1_sym = sympy.geometry.line.Segment(p1_sym, p2_sym)
print(s1_sym.distance(p3_sym))
結果輸出為 9*sqrt(2)/2,這顯然是不對的。
- Debug後發現,呼叫distance() 方法,始終會跳至 Line 類中的distance() 方法,而不是 Segment 類中的 distance() 方法。究其原因,是因為Segment3D這個類繼承了Segment, LinearEntity2D兩個類,而 LinearEntity2D,有繼承了Line類,最後就使用了Line 類中的distance() 方法。
sympy中Segment2D的繼承
class Segment2D(LinearEntity2D, Segment):
將繼承先後順序修改,結果正確。繼承順序改為:
class Segment2D(Segment, LinearEntity2D):
看到這裡,bug的原因找到了,是Python的多重繼承問題引起的!!!
Python多重繼承
新式類和經典類
- Python3 中全部預設是新式類,新式類和經典類的多重繼承關係不同。在菱形繼承(或稱鑽石繼承)中,經典類多繼承屬性搜尋順序: 先深入繼承樹左側,若沒有搜尋到,開始找右側;新式類多繼承屬性搜尋順序: 先水平搜尋,然後再向上移動。
- 更多經典類和新式類的區別,請自行檢索,但個人認為沒必要糾結於二者的區別,新式類是未來,掌握新式類就完全OK。
繼承關係
這裡多重繼承牽涉到的都是新式類。
1. 簡單多重繼承
class Line():
def distance(self):
print('value of A')
class LinearEntity(Line):
pass
class Segment():
def distance(self):
print('value of C')
class Segment2D(LinearEntity, Segment):
pass
test = Segment2D()
test.distance()
列印結果 : value of A
更改Segment2D類對父類的繼承順序:
class Line():
def distance(self):
print('value of A')
class LinearEntity(Line):
pass
class Segment():
def distance(self):
print('value of C')
class Segment2D(Segment, LinearEntity):
pass
test = Segment2D()
test.distance()
列印結果 : value of c
結論:簡單多重繼承,先一直深入搜尋左邊,沒有找到相關屬性/方法,再搜尋右邊
2. 菱形繼承
當一個子類繼承2個父類,而2個父類又都繼承一個基類,構成了一個菱形.
為驗證菱形繼承的繼承關係,修改上面的程式碼,如下:
class Line():
def distance(self):
print('value of A')
class LinearEntity(Line):
pass
class Segment(Line):
def distance(self):
print('value of C')
class Segment2D(LinearEntity, Segment):
pass
test = Segment2D()
test.distance()
列印結果 : value of c
更改Segment2D類對父類的繼承順序:
class Line():
def distance(self):
print('value of A')
class LinearEntity(Line):
pass
class Segment():
def distance(self):
print('value of C')
class Segment2D(Segment, LinearEntity):
pass
test = Segment2D()
test.distance()
列印結果 : value of c
可以看到,不管繼承先後,菱形繼承關係中,都是先左右搜尋,再上下搜尋,即一層一層搜尋。
文末語:文章大部分還是在自己的部落格網站上釋出,更多內容可移步我的個人網站 《浮生,奈若何》,www.linzhongya.top
相關文章
- 多繼承 與 多重繼承繼承
- Python的多重繼承如何使用?python教程Python繼承
- 想問一個比較簡單的問題,java中的Object怎麼可以被多重繼承,JavaObject繼承
- Python多重繼承注意事項!Python教程Python繼承
- python3 筆記20.類的呼叫和多重繼承(多重繼承MRO方法解析順序)Python筆記繼承
- 繼承問題繼承
- 說說C++多重繼承C++繼承
- YTU-OJ-多重繼承繼承
- 多重繼承及虛繼承中物件記憶體的分佈繼承物件記憶體
- delegate 繼承問題繼承
- 模板類的繼承問題繼承
- Python-單繼承中值傳遞的問題Python繼承
- C#如何實現多重繼承C#繼承
- 聊聊iOS中的多繼承和多重代理iOS繼承
- C++ 多級繼承與多重繼承:程式碼組織與靈活性的平衡C++繼承
- JAVA繼承的初始化問題Java繼承
- 【40】明智而審慎地使用多重繼承繼承
- python_類繼承例題Python繼承
- 一文打盡Java繼承的相關問題Java繼承
- Java建構函式的繼承問題Java函式繼承
- 學習Java中遇到的繼承問題Java繼承
- 建構函式的繼承問題 (轉)函式繼承
- python繼承Python繼承
- python 繼承Python繼承
- [提問交流]前臺模板繼承問題繼承
- 18、繼承以及繼承中成員變數和成員方法的重名問題繼承變數
- Python類的繼承Python繼承
- 什麼是繼承?Python繼承的特徵有哪些?繼承Python特徵
- Python的多繼承問題-MRO和C3演算法Python繼承演算法
- 【c++基礎】菱形繼承問題C++繼承
- 【Python】python類的繼承Python繼承
- dubbo繼承springboot出現的問題繼承Spring Boot
- C++繼承一之公有繼承C++繼承
- python之繼承Python繼承
- odoo 繼承(owl繼承、web繼承、view繼承)Odoo繼承WebView
- 如何繼承Date物件?由一道題徹底弄懂JS繼承。繼承物件JS
- python 基礎之繼承、重寫、多繼承Python繼承
- 面試官問:JS的繼承面試JS繼承