2013-12-22 38 views
2

我有以下兩類:功能沒有被覆蓋的子類

class Shape(object): 
    def __init__(self, start_point, *args): 
     self.vertices = [] 
     self.__make_vertices(start_point, *args) 

    def __make_vertices(self, start_point, *args): 
     print "Not Implemented: __make_vertices" 

    def __getitem__(self, *args): 
     return self.vertices.__getitem__(*args) 

class Cube(Shape): 
    def __init__(self, start_point, side_length): 
     Shape.__init__(self, start_point, side_length) 

    def __make_vertices(self, start_point, side_length): 
     append = self.vertices.append 
     start_point = Vector(*(start_point)) 
     i, j, k = side_length*I, side_length*J, side_length*K 
     append(start_point) 
     append(self.vertices[-1] - k) 
     append(self.vertices[-1] - j) 
     append(self.vertices[-1] + k) 
     append(self.vertices[-1] - i) 
     append(self.vertices[-1] - k) 
     append(self.vertices[-1] + j) 
     append(self.vertices[-1] + k) 
     print self.vertices 

當我提出一個新的Cube,我期望我在多維數據集類中定義的__make_vertices函數將被調用,而是我一直獲取Shape__make_vertices函數打印出的消息。我誤解了什麼?

+0

http://php.net/manual/en/language.oop5.overloading.php – 2013-12-22 18:00:25

+0

@Allendar:這是Python,而不是PHP。 – BrenBarn

+0

對不起,我在筆記本電腦後面睡着了,嘿嘿,我的壞:) – 2013-12-22 18:04:49

回答

7

你缺少name mangling

形式__spam的任何標識符(至少兩個前導下劃線,至多一個結尾下劃線)的文本上與_classname__spam,classname即當前的類名前導下劃線替​​換(s)剝離。只要它在類的定義內發生,就不會考慮標識符的語法位置。

換句話說,你應該只使用屬性/方法的名稱以兩個下劃線開始的時候你特別希望子類覆蓋它們,而是爲他們提供自己的私人版本。這很少見,所以通常你不需要使用雙下劃線名稱。

+1

通常,人們將兩個主要下劃線與* private *成員關聯,並且一個帶有* protected *(或其他內部成員)的主要下劃線關聯。所以如果你想允許重寫,最多隻能使用一個下劃線。 – poke

+0

@poke:這是真的,但人們認爲他們想要私有/受保護屬性的很多原因在Python中並不真正有效。使用單個下劃線不是訪問控制機制,它是關於哪些方法可以作爲面向外API的一部分的文檔約定。即使使用雙下劃線方法也不會阻止訪問,它只是更改名稱。所以我避開使用這些術語,因爲他們可能會混淆人們嘗試使用語法來獲取在Python中並不存在的訪問隱藏功能。 – BrenBarn

+0

做私有方法的一種更好的方法是不要在類中定義方法!相反,在同一個包中傳遞一個函數來執行該操作,即'def _private_foo(obj,arg1,arg2,...)'。 – wheaties