2011-02-08 28 views
7

希望這是非常明顯的:的Python:從派生類中獲取基類值

class myParent(): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print myParent.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers() 

我想單獨設置parentNumber,進而達到通過該子類號,在這種情況下使用它的一些乘法。

我是OOP領域的新手,所以任何關於繼承的一般指針都是受歡迎的!

更多信息: 我設計了基於VFX-項目的項目管理解決方案,並正在與類和繼承玩,看看他們如何能幫助我最。

現在,我已經得到了頂級課程,項目和一個派生類,Shot。 Shot具有一個self.length變量和特定鏡頭的長度。它還有一個getLengthInSeconds()方法,它使用self.length和Project.fps來確定長度(以秒爲單位)。 Project有一個setFps()方法,其中在創建類的實例之後設置fps。

我很習慣以self爲前綴的變量。並沒有用更多的「全局」變量在沒有自我的情況下嘗試過很多類。 。如果我把所有東西都做成全球化的東西,那麼我就可以毫無麻煩地使用Project.fps,但是我在我的neckhair中收到了一個「糟糕的編程習慣」警告。也許有更好,更整潔的方式?

編輯:

一些閱讀後,超()似乎有點危險,有點比我更需要我的想法。我主要有單繼承類,甚至不知道如何使用鑽石層次結構。是否有更安全的方式來訪問超類變量和方法,不包括super()?

編輯:

還好吧,看看這是有道理的,或者如果我想這都是錯誤的。

我正在尋找類和繼承作爲組和孩子。一個孩子知道它是父母,所有的價值。一個孩子到另一個父母知道父母的價值觀。我試圖完成的是將所有鏡頭創建爲項目的一部分。現在,我從Project()類中創建Shot()實例,將實例添加到項目()實例中保留的鏡頭列表中。

class myParent(object): 
    def __init__(self): 
     self.parent_id = '' 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name)) 

    def getChildren(self): 
     return self.children 

    def setParentId(self, id): 
     self.parentId = id 

class myChild(myParent): 
    def __init__(self, id): 
     super(myChild, self).__init__() 
     self.id = id 

    def getParentId(self): 
     return self.parent_id 

p = myParent() 
p.setParentId('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId() 

我有點看這裏的邏輯錯誤的步驟,但它周圍沒有真正的方法.. 好像每個孩子得到父母的新實例這種方式,在parent_id始終是一個空字符串。

+0

你需要調用父類的構造。 – 2011-02-08 16:32:31

回答

5
class myParent(object): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     myParent.__init__(self) 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print self.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers()

您通常可以管理不super就好了,當你不具備多重繼承或其他邊境情況,但如果基類發生更改,則需要記住將init(以及任何其他顯式引用myParent的方法)的父類名更改。

如果您父母的__init__需要參數,您需要將其傳遞給孩子的__init__

class myParent(object): 
    def __init__(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     myParent.__init__(self, customParam) 
     self.childNumber = 4

如果你不喜歡customParam的重複在所有子類,有一個名爲二期建設替代OO模式,它的工作原理是這樣的:

class myParent(object): 
    def customInit(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     self.childNumber = 4 

p = Child() 
p.customInit(10) 
p.multiplyNumbers() 

在這個模式中,你不需要重複任何父母的參數,甚至在孩子中調用父母的__init__,但缺點是在創建對象時需要始終調用輔助構造函數,否則對象將部分未初始化。

UPDATE(回答這個問題更新):

你似乎在這裏混合父母的兩個不相關的概念。繼承是關於類型層次結構的,你似乎在所有權層次結構之後(is-a與has-a)。

我會組織你的更新代碼:

class myParent(object): 
    def __init__(self, parentId): 
     self.id = parentId 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name, self)) 

    def getChildren(self): 
     return self.children 

class myChild(object): 
    def __init__(self, childId, parent): 
     self.id = childId 
     self.parent = parent 

    def getParentId(self): 
     return self.parent.id 

p = myParent('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId()
5

您只需告訴Child即可從myParent運行初始化。之後,當前實例(self已具有所有實例屬性myParent將具有的實例("is a"),因此您可以使用self.parentNumber。通過將super(Child, self).__init__()納入Child.__init__(理想情況下,在第一行)可以工作,但當基類發生更改或多重繼承時,它可能是錯誤的(以微妙的方式)。如果您使用的是Python 3,則可以將所有參數刪除到super

還要注意的是

class C(object): 
    x = ... 

class C(object): 
    def __init__(self): 
     self.x = ... 

前者截然不同創建一個類變量,這是由C所有實例共享。後者創建一個實例變量,每個實例都有自己的實例。 (同樣,全局變量不綁定到實例 - 但我認爲你在談論以上?)

+1

+1 ..它應該是`multiplyNumbers`中的`self.parentNumber`。 – sdolan 2011-02-08 16:36:57

+0

@sdolan:是的,包括在內。 – delnan 2011-02-08 16:41:44