2014-10-08 228 views
0

我是OOP和Python的新手。幾乎所有我知道的是自學成才的,所以如果你能提供一些鏈接供我閱讀,我將不勝感激,因爲我不知道我應該尋求什麼確切的術語來澄清我的疑惑。類,隱藏屬性和繼承

這是我到目前爲止的代碼:

class Point(object): 
    x = 2 
    y = 3 

    def __init__(self, x, y): 
     self.x_a = x 
     self.y_b = y 

class RectPoint(Point): 

    def __init__(self, x, y): 
     self.x_1 = x 
     self.y_1 = y 
     self.dist = (x*x + y*y)**0.5 


class CircPoint(Point): 
    pass 

a = Point(3,4) 
b = CircPoint(3,4) 
c = RectPoint(3,4) 

print a.x  # 2 
print a.y  # 3 
print a.x_a # 3 
print a.y_b # 4 
print b.x  # 2 
print b.y  # 3 
print b.x_a # 3 
print b.y_b # 4 
print c.x  # 2 
print c.y  # 3 
print c.x_1 # 3 
print c.y_1 # 4 
print c.dist # 5.0 
print c.x_a # AttributeError 
print c.y_b # AttributeError 

爲什麼是CircPoint屬性self.x_aself.y_b不適用於類RectPoint但可用?我將如何使它們可用?

此外,爲什麼self.xself.y可用於兩個類別RectPointCircPoint

進一步閱讀的鏈接也將讚賞(到位的解釋)

+1

我讓更有經驗的用戶詳細解釋;但用幾句話來說,'a'顯然有它應有的一切; 'b'是一個'CircPoint',它繼承了'Point'的所有內容,並且什麼也沒加,所以它擁有'Point'所有的東西。另一方面,'c'是一個'RectPoint',一個從'Point'繼承'x'和'y'的類,但是你定義了一個不同的'__init__'方法 - 所以這覆蓋了原始類的方法。 – Roberto 2014-10-08 16:50:19

回答

4

您的RectPoint.__init__方法面具Point.__init__方法。由於Point.__init__未針對RectPoint實例執行,因此self.x_aself.y_b屬性從不設置。這是因爲Python首先搜索實例,然後搜索類,然後搜索屬性的基類。在這裏,方法真的是專用屬性。在創建類的實例時,Python會在類上查找__init__方法,然後在基類上查找。

CircPoint沒有實現自己__init__所以Point.__init__是發現和使用,self.x_aself.y_b集。

對於xy,請做特定的類別屬性; Python使用相同的搜索順序來查找它們;它們沒有設置在實例上,最終在基類上找到;要麼是因爲您有Point實例或Point的子類,並且搜索了該子類的基類。

您可以明確呼叫從RectPoint.__init__的覆蓋__init__方法:

class RectPoint(Point): 
    def __init__(self, x, y): 
     super(RectPoint, self).__init__(x, y) 
     self.x_1 = x 
     self.y_1 = y 
     self.dist = (x*x + y*y)**0.5 

super() function,您可以訪問原來Point.__init__方法在這裏,首先調用它。然後該方法設置self.x_aself.y_b屬性,之後它將返回並且RectPoint.__init__方法將設置更多屬性。

​​涵蓋了一切細節。

+0

+1我只是加了一個(我在我自己的 - 被遺棄的答案中),雖然在某些語言中'RectPoint'會隱式地調用'Point'的構造函數,但Python不是這些語言之一。 – chepner 2014-10-08 16:54:30

+0

非常感謝。我還有一個問題,我不確定是否應該在這裏插入它或將它作爲一個單獨的。對'__init__'方法中沒有初始化的變量有沒有實際應用?即從我的代碼屬性'x'和'y'? – 2014-10-08 17:07:43

+0

@ M.Klugerford:是的,您可以將它們用作默認值,或者在所有實例之間共享信息。將這與建築論文相比較;您可以將基類,類和實例分層疊加,並通過圖層查看數據,但*設置*實例上的屬性將隱藏類上的屬性(掩碼)。但是你總是可以用'ClassObject.attribute_name = new_value'在類上直接設置屬性*。 – 2014-10-08 17:30:56

1

RectPoint實例沒有x_ay_b屬性,是因爲你的RectPoint.__init__方法不會定義他們,永遠不會調用Point.__init__這將。

xy是類屬性,可在定義它們的類,任何子類和這些類的實例上使用(除非通過在子類或實例上設置屬性來重寫)。 self.x首先在實例上尋找x,然後在該類及其父類上找不到它。

1

當你重寫初始化在Python類,你仍然需要給你打電話從繼承的類的初始化方法或者那些屬性將不會提供給你的子類。你用超級方法做到這一點。在RectPoint,昌你的init方法像這樣:

def __init__(self, *args, **kwargs): 
    self.x_1 = x 
    self.y_1 = y 
    self.dist = (x*x + y*y)**0.5 
    super(RectPoint,self).__init__(*args,**kwargs)