<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                前面講過的“繼承”,是類的一個重要特征,在編程中用途很多。這里要說兩個在理解和實踐上有爭議的話題:多態和封裝。所謂爭議,多來自于對同一個現象不同角度的理解,特別是有不少經驗豐富的程序員,還從其它語言的角度來詮釋python的多態等。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/211.md#多態)多態 在網上搜索一下,發現對python的多態問題,的確是仁者見仁智者見智。 作為一個初學者,不一定要也沒有必要、或者還沒有能力參與這種討論。但是,應該理解python中關于多態的基本體現,也要對多態有一個基本的理解。 ~~~ >>> "This is a book".count("s") 2 >>> [1,2,4,3,5,3].count(3) 2 ~~~ 上面的`count()`的作用是數一數某個元素在對象中出現的次數。從例子中可以看出,我們并沒有限定count的參數。類似的例子還有: ~~~ >>> f = lambda x,y:x+y ~~~ 還記得這個lambda函數嗎?如果忘記了,請復習[函數(4)](https://github.com/qiwsir/StarterLearningPython/blob/master/204.md)中對此的解釋。 ~~~ >>> f(2,3) 5 >>> f("qiw","sir") 'qiwsir' >>> f(["python","java"],["c++","lisp"]) ['python', 'java', 'c++', 'lisp'] ~~~ 在那個lambda函數中,我們沒有限制參數的類型,也一定不能限制,因為如果限制了,就不是pythonic了。在使用的時候,可以給參數任意類型,都能到的不報錯的結果。當然,這樣做之所以合法,更多的是來自于`+`的功能強悍。 以上,就體現了“多態”。當然,也有人就此提出了反對意見,因為本質上是在參數傳入值之前,python并沒有確定參數的類型,只能讓數據進入函數之后再處理,能處理則罷,不能處理就報錯。例如: ~~~ >>> f("qiw", 2) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <lambda> TypeError: cannot concatenate 'str' and 'int' objects ~~~ 本教程由于不屬于這種概念爭論范疇,所以不進行這方面的深入探索,僅僅是告訴各位讀者相關信息。并且,本教程也是按照“人云亦云”的原則,既然大多數程序員都在討論多態,那么我們就按照大多數人說的去介紹(盡管有時候真理掌握在少數人手中)。 “多態”,英文是:Polymorphism,在臺灣被稱作“多型”。維基百科中對此有詳細解釋說明。 > 多型(英語:Polymorphism),是指物件導向程式執行時,相同的訊息可能會送給多個不同的類別之物件,而系統可依據物件所屬類別,引發對應類別的方法,而有不同的行為。簡單來說,所謂多型意指相同的訊息給予不同的物件會引發不同的動作稱之。 再簡化的說法就是“有多種形式”,就算不知道變量(參數)所引用的對象類型,也一樣能進行操作,來者不拒。比如上面顯示的例子。在python中,更為pythonic的做法是根本就不進行類型檢驗。 例如著名的`repr()`函數,它能夠針對輸入的任何對象返回一個字符串。這就是多態的代表之一。 ~~~ >>> repr([1,2,3]) '[1, 2, 3]' >>> repr(1) '1' >>> repr({"lang":"python"}) "{'lang': 'python'}" ~~~ 使用它寫一個小函數,還是作為多態代表的。 ~~~ >>> def length(x): ... print "The length of", repr(x), "is", len(x) ... >>> length("how are you") The length of 'how are you' is 11 >>> length([1,2,3]) The length of [1, 2, 3] is 3 >>> length({"lang":"python","book":"itdiffer.com"}) The length of {'lang': 'python', 'book': 'itdiffer.com'} is 2 ~~~ 不過,多態也不是萬能的,如果這樣做: ~~~ >>> length(7) The length of 7 is Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in length TypeError: object of type 'int' has no len() ~~~ 報錯了。看錯誤提示,明確告訴了我們`object of type 'int' has no len()`。 在諸多介紹多態的文章中,都會有這樣關于貓和狗的例子。這里也將代碼貼出來,讀者去體會所謂多態體現。其實,如果你進入了python的語境,有時候是不經意就已經在應用多態特性呢。 ~~~ #!/usr/bin/env python # coding=utf-8 "the code is from: http://zetcode.com/lang/python/oop/" __metaclass__ = type class Animal: def __init__(self, name=""): self.name = name def talk(self): pass class Cat(Animal): def talk(self): print "Meow!" class Dog(Animal): def talk(self): print "Woof!" a = Animal() a.talk() c = Cat("Missy") c.talk() d = Dog("Rocky") d.talk() ~~~ 保存后運行之: ~~~ $ python 21101.py Meow! Woof! ~~~ 代碼中有Cat和Dog兩個類,都繼承了類Animal,它們都有`talk()`方法,輸入不同的動物名稱,會得出相應的結果。 關于多態,有一個被稱作“鴨子類型”(duck typeing)的東西,其含義在維基百科中被表述為: > 在程序設計中,鴨子類型(英語:duck typing)是動態類型的一種風格。在這種風格中,一個對象有效的語義,不是由繼承自特定的類或實現特定的接口,而是由當前方法和屬性的集合決定。這個概念的名字來源于由James Whitcomb Riley提出的鴨子測試(見下面的“歷史”章節),“鴨子測試”可以這樣表述:“當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。” 對于鴨子類型,也是有爭議的。這方面的詳細信息,讀者可以去看有關維基百科的介紹。 對于多態問題,最后還要告誡讀者,類型檢查是毀掉多態的利器,比如type、isinstance以及isubclass函數,所以,一定要慎用這些類型檢查函數。 ## [](https://github.com/qiwsir/StarterLearningPython/blob/master/211.md#封裝和私有化)封裝和私有化 在正式介紹封裝之前,先扯個笑話。 > 某軟件公司老板,號稱自己懂技術。一次有一個項目要交付給客戶,但是他有不想讓客戶知道實現某些功能的代碼,但是交付的時候要給人家代碼的。于是該老板就告訴程序員,“你們把那部分核心代碼封裝一下”。程序員聽了之后,迷茫了。 不知道你有沒有笑。 “封裝”,是不是把代碼寫到某個東西里面,“人”在編輯器中打開,就看不到了呢?除非是你的顯示器壞了。 在程序設計中,封裝(Encapsulation)是對object的一種抽象,即將某些部分隱藏起來,在程序外部看不到,即無法調用(不是人用眼睛看不到那個代碼,除非用某種加密或者混淆方法,造成現實上的困難,但這不是封裝)。 要了解封裝,離不開“私有化”,就是將類或者函數中的某些屬性限制在某個區域之內,外部無法調用。 python中私有化的方法也比較簡單,就是在準備私有化的屬性(包括方法、數據)名字前面加雙下劃線。例如: ~~~ #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class ProtectMe: def __init__(self): self.me = "qiwsir" self.__name = "kivi" def __python(self): print "I love Python." def code(self): print "Which language do you like?" self.__python() if __name__ == "__main__": p = ProtectMe() print p.me print p.__name ~~~ 運行一下,看看效果: ~~~ $ python 21102.py qiwsir Traceback (most recent call last): File "21102.py", line 21, in <module> print p.__name AttributeError: 'ProtectMe' object has no attribute '__name' ~~~ 查看報錯信息,告訴我們沒有`__name`那個屬性。果然隱藏了,在類的外面無法調用。再試試那個函數,可否? ~~~ if __name__ == "__main__": p = ProtectMe() p.code() p.__python() ~~~ 修改這部分即可。其中`p.code()`的意圖是要打印出兩句話:`"Which language do you like?"`和`"I love Python."`,`code()`方法和`__python()`方法在同一個類中,可以調用之。后面的那個`p.__python()`試圖調用那個私有方法。看看效果: ~~~ $ python 21102.py Which language do you like? I love Python. Traceback (most recent call last): File "21102.py", line 23, in <module> p.__python() AttributeError: 'ProtectMe' object has no attribute '__python' ~~~ 如愿以償。該調用的調用了,該隱藏的隱藏了。 用上面的方法,的確做到了封裝。但是,我如果要調用那些私有屬性,怎么辦? 可以使用`property`函數。 ~~~ #!/usr/bin/env python # coding=utf-8 __metaclass__ = type class ProtectMe: def __init__(self): self.me = "qiwsir" self.__name = "kivi" @property def name(self): return self.__name if __name__ == "__main__": p = ProtectMe() print p.name ~~~ 運行結果: ~~~ $ python 21102.py kivi ~~~ 從上面可以看出,用了`@property`之后,在調用那個方法的時候,用的是`p.name`的形式,就好像在調用一個屬性一樣,跟前面`p.me`的格式相同。 看來,封裝的確不是讓“人看不見”。
                  <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>

                              哎呀哎呀视频在线观看