2017-02-03 71 views
0

我有兩個很簡單的類寫在下面。 Human繼承自Mammal類。當我打電話給print(jo.drinkMe("sage"))時,我希望打印出「生病」,但打印出「良好」。我認爲self.problem中的Human類會覆蓋Mammal類中的self.problem。我需要做些什麼才能讓我的代碼打印出「病態」結果?如何防止父類的實例變量被python中的子類覆蓋?

class Mammal: 
    def __init__(self): 
     self.problem = "sage" 
     self.result = "sick" 

    def drinkMe(self,tea): 
     if tea == self.problem: 
      return self.result 
     else: 
      return "fine" 

class Human(Mammal): 
    def __init__(self): 
     super().__init__() 
     self.problem = "paint" 
     self.result = "die" 
    def drinkMe(self,tea): 
     if tea == self.problem: 
      return self.result 
     else: 
      return super().drinkMe(tea) 

jo = Human() 
to = Mammal() 
print(jo.drinkMe("sage")) 
+2

你想讓這些問題變量分開嗎?如果您嘗試執行'jo.problem',會發生什麼?如果對第一個問題的回答是「是」,對第二個問題的回答是「無關緊要」或「你不應該這樣做」,那麼這可能是其中一個時機,使用領先者實際上是一個好主意雙下劃線。 – user2357112

+1

「人類」和「哺乳動物」類都沒有屬性「問題」,所以它不能被覆蓋。 –

+1

@ juanpa.arrivillaga雖然沒有解釋,但這並不是一個好主意。 –

回答

2

您遇到的問題是,Mammal只設置時,它的實例化的實例屬性problemresultjo = Human()實例化一個Mammal對象,但隨後將problemresult屬性變爲其自己的屬性。要詳細,您有:

class Human(Mammal): 
    def __init__(self): 
     super().__init__() 
     # calls `Mammal.__init__()`, which sets 
     # self.problem = "sage" 
     # self.result = "sick" 
     self.problem = "paint" 
     self.result = "die" 
     # overwrites what `Mammal.__init__()` did a 
     # couple lines ago. 
    ... 

你可能反而做的事:

class Mammal(object): 
    problem = "sage" 
    result = "sick" 

    def drink_me(self, tea): 
     if tea == self.problem: 
      return self.result 
     else: 
      return "fine" 


class Human(Mammal): 
    problem = "paint" 
    result = die 

    def drink_me(self, tea): 
     if tea == self.problem: 
      return self.result 
     else: 
      return super().drink_me(tea) 
+0

「jo = Human()永遠不會實例化哺乳動物對象」 - 你是什麼意思?它實例化Mammal對象'jo'。這並不像他們忘記調用'super().__ init__',而是跳過了超類的初始化;他們只是壓倒了超類的'__init__'設置的值。 – user2357112

+0

@ user2357112是真的,我說得不好。我將刪除並重新編寫。 –

+0

@ user2357112更好嗎? –

2

我希望這有助於。它與你的原始代碼有一點不同,但老實說你發佈的代碼需要一些凌亂的super()調用。我認爲,你的目標是對的Mammal()與結果的附加選項從drinkMe()

一個子類關於採取這種方法是什麼:現在有飲料和結果的字典中的所有Mammals。子類用它們自己的對飲料的自定義響應來更新這個字典。這樣你就有一個函數返回飲料的響應。如果一個實例喝了一些沒有響應集的東西,會發生什麼?現在,您只需在drinkMe()內添加一次異常處理。

class Mammal: 
    def __init__(self): 
     self.problems = {'sage': 'sick'} 

    def drinkMe(self, tea): 
     return self.problems[tea] 


class Human(Mammal): 
    def __init__(self): 
     super().__init__() 
     self.problems.update({'paint': 'die'}) 

jo = Human() 
print(jo.drinkMe("sage")) 

編輯:要多加評論,爲什麼你的原始代碼打印fine,而不是sick

當您安裝Human時,調用jo,jo.problem設置爲paint。所以,jo.drinkMe調用super.drinkMe,它再次檢查是否tea == self.problem。但請記住,你仍然沒有改變jo.problem。它仍然設置爲paint,因此返回fine

self是實例本身,在這種情況下,它是jo,當你調用super.drinkMe()super.__init__()不會再次運行,因此self.problem仍設置爲不管它是什麼。

0

我發現了一個非常簡單的方法來防止在Human中聲明的實例變量覆蓋Mammal中的實例變量。碼基本上只是重新分配的self.problemself.result每次drink_me值被稱爲:

class Mammal: 

    def __init__(self): 
     self.problem = "sage" 
     self.result = "sick" 

    def drinkMe(self,tea): 
     if tea == self.problem: 
      return self.result 
     else: 
      return "fine" 
class Human(Mammal): 
    def __init__(self): 
     super().__init__() 
     self.problem = "paint" 
     self.result = "die" 
    def drinkMe(self,tea): 
     result = '' 
     if tea == self.problem: 
      return self.result 
     else: 
      super().__init__() 
      result = super().drinkMe(tea) 
      self.__init__() 
      return(result) 
jo = Human() 
print(jo.drinkMe("sage")) 
print(jo.drinkMe("paint")) 

此代碼首先打印服務「生病」,然後「死」。