2012-01-13 165 views
23

我是剛剛開始學習Python的Java人。就拿這個例子:使用__init__繼承Python中的屬性

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 

class Teenager(Person): 
    def __init__(self, name, phone, website): 
     self.name=name 
     self.phone=phone 
     self.website=website 

我敢肯定有很多冗餘代碼(我知道在Java中,有一段代碼位大量裁員以上)。

哪些部分對於哪些屬性已經從父類繼承而言是多餘的?

回答

29

當爲python中的類編寫__init__函數時,您應該始終調用其超類的__init__函數。我們可以用它來直接傳遞相關屬性的超類,所以你的代碼應該是這樣的:

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def __init__(self, name, phone, website): 
     Person.__init__(self, name, phone) 
     self.website=website 

正如其他人所指出的那樣,你可以用

更換線

Person.__init__(self, name, phone) 

super(Teenager, self).__init__(name, phone) 

和代碼將做同樣的事情。這是因爲python instance.method(args)只是Class.method(instance, args)的簡寫。如果你想使用super,你需要確保你指定了object作爲Person的基類,就像我在我的代碼中所做的那樣。

python documentation有關於如何使用關鍵字super的更多信息。在這種情況下,重要的是,它告訴Python來尋找方法__init__self超類,是不是Teenager

+2

請注意,如果您使用的是Python 2.x,則必須將'object'明確列出爲'Person'的基類以便使用'super()'。否則,你必須使用'Person .__ init__'形式。 – chepner 2012-01-13 17:17:58

+0

@chepner你能提供一個參考嗎?我找不到一個。 – murgatroid99 2012-01-13 17:19:08

+0

http://docs.python.org/library/functions.html#super表示super()僅支持新樣式類,它在Python 2.x中是那些從'object'繼承的類。 – chepner 2012-01-13 17:21:59

5

Python中的屬性,當他們在構造和父類的構造函數定義是不能繼承的不叫,除非你手動做這一切:

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     Person.__init__(self, name, phone) # Call parent class constructor. 
     self.website=website 

更多在這裏:http://docs.python.org/tutorial/classes.html#inheritance

1

__init__,不像Java的構造,不會自動要求繼承層次結構中的每個類 - 你需要ŧ o自己動手。

此外,您的所有對象層次結構都應根據object(特殊情況除外)。

您的代碼應閱讀:

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     super(Teenager, self).__init__(name, phone) 
     self.website=website 

super它的第二個參數(self),這將調用下一個函數的函數列表來調用每個名稱(以下簡稱「方法解析順序創建一個委託「)。這與調用超類方法並不完全相同,就像在Java中發生的那樣。

你也可以寫super(type(self), self).__init__(name, phone),但如果你從這個類繼承進一步,type(self)可能不是Teenager,你可以有一個無限遞歸。這是事實的一個實際結果,即您正在使用具有差異MRO的委託對象,而不是直接調用超類構造函數。

11

稍微清潔的方式,我喜歡這樣做:

class Teenager(Person): 
     def __init__(self, *args, **kwargs): 
      self.website=kwargs.pop('website') 
      super(Teenager, self).__init__(*args, **kwargs) 

它沒有多大的差別在這種情況下,但是當你有一個__init__一噸的參數,它使生活更輕鬆。

+0

Upvoted使用* args和** kwargs(...在很多參數的情況下是有效的)。 – 2015-11-23 17:53:23