<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                本節介紹類中一個非常重要的東西——繼承,其實也沒有那么重要,只是聽起來似乎有點讓初學者暈頭轉向,然后就感覺它屬于很高級的東西,真是情況如何?學了之后你自然有感受。 在現實生活中,“繼承”意味著一個人從另外一個人那里得到了一些什么,比如“繼承革命先烈的光榮傳統”、“某人繼承他老爹的萬貫家產”等。總之,“繼承”之后,自己就在所繼承的方面省力氣、不用勞神費心,能輕松得到,比如繼承了萬貫家產,自己就一夜之間變成富豪。如果繼承了“革命先烈的光榮傳統”,自己是不是一下就變成革命者呢? 當然,生活中的繼承或許不那么嚴格,但是編程語言中的繼承是有明確規定和穩定的預期結果的。 > 繼承(Inheritance)是面向對象軟 件技術當中的一個概念。如果一個類別A“繼承自”另一個類別B,就把這個A稱為“B的子類別”,而把B稱為“A的父類別”,也可以稱“B是A的超類”。 > > 繼承可以使得子類別具有父類別的各種屬性和方法,而不需要再次編寫相同的代碼。在令子類別繼承父類別的同時,可以重新定義某些屬性,并重寫某些方法,即覆蓋父類別的原有屬性和方法,使其獲得與父類別不同的功能。另外,為子類別追加新的屬性和方法也是常見的做法。 (源自維基百科) 由上面對繼承的表述,可以簡單總結出繼承的意圖或者好處: * 可以實現代碼重用,但不是僅僅實現代碼重用,有時候根本就沒有重用 * 實現屬性和方法繼承 誠然,以上也不是全部,隨著后續學習,對繼承的認識會更深刻。好友令狐蟲曾經這樣總結繼承: > 從技術上說,OOP里,繼承最主要的用途是實現多態。對于多態而言,重要的是接口繼承性,屬性和行為是否存在繼承性,這是不一定的。事實上,大量工程實踐表明,重度的行為繼承會導致系統過度復雜和臃腫,反而會降低靈活性。因此現在比較提倡的是基于接口的輕度繼承理念。這種模型里因為父類(接口類)完全沒有代碼,因此根本談不上什么代碼復用了。 > > 在Python里,因為存在Duck Type,接口定義的重要性大大的降低,繼承的作用也進一步的被削弱了。 > > 另外,從邏輯上說,繼承的目的也不是為了復用代碼,而是為了理順關系。 他是大牛,或許讀者感覺比較高深,沒關系,隨著你的實踐經驗的積累,你也能對這個問題有自己獨到的見解。 或許你也要問我的觀點是什么?我的觀點就是:走著瞧!怎么理解?繼續向下看,只有你先深入這個問題,才能跳到更高層看這個問題。小馬過河的故事還記得吧?只有親自走入河水中,才知道河水的深淺。 對于python中的繼承,前面一直在使用,那就是我們寫的類都是新式類,所有新式類都是繼承自object類。不要忘記,新式類的一種寫法: ~~~ class NewStyle(object): pass ~~~ 這就是典型的繼承。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/209.md#基本概念)基本概念 ~~~ #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class Person: def speak(self): print "I love you." def setHeight(self): print "The height is: 1.60m ." def breast(self, n): print "My breast is: ",n class Girl(Person): def setHeight(self): print "The height is:1.70m ." if __name__ == "__main__": cang = Girl() cang.setHeight() cang.speak() cang.breast(90) ~~~ 上面這個程序,保存之后運行: ~~~ $ python 20901.py The height is:1.70m . I love you. My breast is: 90 ~~~ 對以上程序進行解釋,從中體會繼承的概念和方法。 首先定義了一個類Person,在這個類中定義了三個方法。注意,沒有定義初始化函數,初始化函數在類中不是必不可少的。 然后又定義了一個類Girl,這個類的名字后面的括號中,是上一個類的名字,這就意味著Girl繼承了Person,Girl是Person的子類,Person是Girl的父類。 既然是繼承了Person,那么Girl就全部擁有了Person中的方法和屬性(上面的例子雖然沒有列出屬性)。但是,如果Girl里面有一個和Person同樣名稱的方法,那么就把Person中的同一個方法遮蓋住了,顯示的是Girl中的方法,這叫做方法的**重寫**。 實例化類Girl之后,執行實例方法`cang.setHeight()`,由于在類Girl中重寫了setHeight方法,那么Person中的那個方法就不顯作用了,在這個實例方法中執行的是類Girl中的方法。 雖然在類Girl中沒有看到speak方法,但是因為它繼承了Person,所以`cang.speak()`就執行類Person中的方法。同理`cang.breast(90)`,它們就好像是在類Girl里面已經寫了這兩個方法一樣。既然繼承了,就是我的了。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/209.md#多重繼承)多重繼承 所謂多重繼承,就是只某一個類的父類,不止一個,而是多個。比如: ~~~ #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class Person: def eye(self): print "two eyes" def breast(self, n): print "The breast is: ",n class Girl: age = 28 def color(self): print "The girl is white" class HotGirl(Person, Girl): pass if __name__ == "__main__": kong = HotGirl() kong.eye() kong.breast(90) kong.color() print kong.age ~~~ 在這個程序中,前面有兩個類:Person和Girl,然后第三個類HotGirl繼承了這兩個類,注意觀察繼承方法,就是在類的名字后面的括號中把所繼承的兩個類的名字寫上。但是第三個類中什么方法也沒有。 然后實例化類HotGirl,既然繼承了上面的兩個類,那么那兩個類的方法就都能夠拿過來使用。保存程序,運行一下看看 ~~~ $ python 20902.py two eyes The breast is: 90 The girl is white 28 ~~~ 值得注意的是,這次在類Girl中,有一個`age = 28`,在對HotGirl實例化之后,因為繼承的原因,這個類屬性也被繼承到HotGirl中,因此通過實例屬性`kong.age`一樣能夠得到該數據。 由上述兩個實例,已經清楚看到了繼承的特點,即將父類的方法和屬性全部承接到子類中;如果子類重寫了父類的方法,就使用子類的該方法,父類的被遮蓋。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/209.md#多重繼承的順序)多重繼承的順序 多重繼承的順序很必要了解。比如,如果一個子類繼承了兩個父類,并且兩個父類有同樣的方法或者屬性,那么在實例化子類后,調用那個方法或屬性,是屬于哪個父類的呢?造一個沒有實際意義,純粹為了解決這個問題的程序: ~~~ #!/usr/bin/env python # coding=utf-8 class K1(object): def foo(self): print "K1-foo" class K2(object): def foo(self): print "K2-foo" def bar(self): print "K2-bar" class J1(K1, K2): pass class J2(K1, K2): def bar(self): print "J2-bar" class C(J1, J2): pass if __name__ == "__main__": print C.__mro__ m = C() m.foo() m.bar() ~~~ 這段代碼,保存后運行: ~~~ $ python 20904.py (<class '__main__.C'>, <class '__main__.J1'>, <class '__main__.J2'>, <class '__main__.K1'>, <class '__main__.K2'>, <type 'object'>) K1-foo J2-bar ~~~ 代碼中的`print C.__mro__`是要打印出類的繼承順序。從上面清晰看出來了。如果要執行foo()方法,首先看J1,沒有,看J2,還沒有,看J1里面的K1,有了,即C==>J1==>J2==>K1;bar()也是按照這個順序,在J2中就找到了一個。 這種對繼承屬性和方法搜索的順序稱之為“廣度優先”。 新式類用以及python3.x中都是按照此順序原則搜尋屬性和方法的。 但是,在舊式類中,是按照“深度優先”的順序的。因為后面讀者也基本不用舊式類,所以不舉例。如果讀者愿意,可以自己模仿上面代碼,探索舊式類的“深度優先”含義。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/209.md#super函數)super函數 對于初始化函數的繼承,跟一般方法的繼承,還有點不同。可以看下面的例子: ~~~ #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class Person: def __init__(self): self.height = 160 def about(self, name): print "{} is about {}".format(name, self.height) class Girl(Person): def __init__(self): self.breast = 90 def about(self, name): print "{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast) if __name__ == "__main__": cang = Girl() cang.about("canglaoshi") ~~~ 在上面這段程序中,類Girl繼承了類Person。在類Girl中,初始化設置了`self.breast = 90`,由于繼承了Person,按照前面的經驗,Person的初始化函數中的`self.height = 160`也應該被Girl所繼承過來。然后在重寫的about方法中,就是用`self.height`。 實例化類Girl,并執行`cang.about("canglaoshi")`,試圖打印出一句話`canglaoshi is a hot girl, she is about 160, and her bereast is 90`。保存程序,運行之: ~~~ $ python 20903.py Traceback (most recent call last): File "20903.py", line 22, in <module> cang.about("canglaoshi") File "20903.py", line 18, in about print "{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast) AttributeError: 'Girl' object has no attribute 'height' ~~~ 報錯! 程序員有一句名言:不求最好,但求報錯。報錯不是壞事,是我們長經驗的時候,是在告訴我們,那么做不對。 重要的是看報錯信息。就是我們要打印的那句話出問題了,報錯信息顯示`self.height`是不存在的。也就是說類Girl沒有從Person中繼承過來這個屬性。 原因是什么?仔細觀察類Girl,會發現,除了剛才強調的about方法重寫了,`__init__`方法,也被重寫了。不要認為它的名字模樣奇怪,就不把它看做類中的方法(函數),它跟類Person中的`__init__`重名了,也同樣是重寫了那個初始化函數。 這就提出了一個問題。因為在子類中重寫了某個方法之后,父類中同樣的方法被遮蓋了。那么如何再把父類的該方法調出來使用呢?縱然被遮蓋了,應該還是存在的,不要浪費了呀。 python中有這樣一種方法,這種方式是被提倡的方法:super函數。 ~~~ #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class Person: def __init__(self): self.height = 160 def about(self, name): print "{} is about {}".format(name, self.height) class Girl(Person): def __init__(self): super(Girl, self).__init__() self.breast = 90 def about(self, name): print "{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast) super(Girl, self).about(name) if __name__ == "__main__": cang = Girl() cang.about("canglaoshi") ~~~ 在子類中,`__init__`方法重寫了,為了調用父類同方法,使用`super(Girl, self).__init__()`的方式。super函數的參數,第一個是當前子類的類名字,第二個是self,然后是點號,點號后面是所要調用的父類的方法。同樣在子類重寫的about方法中,也可以調用父類的about方法。 執行結果: ~~~ $ python 20903.py canglaoshi is a hot girl, she is about 160, and her breast is 90 canglaoshi is about 160 ~~~ 最后要提醒注意:super函數僅僅適用于新式類。當然,你一定是使用的新式類。“喜新厭舊”是程序員的嗜好。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看