Python設計模式面向對象編程
- 2021 年 1 月 23 日
- 筆記
前言
本篇文章是基於極客時間王爭的《設計模式之美》做的總結和自己的理解。
說到面向對象編程,作為一個合格的Pythoner,可以說信手拈來。畢竟在Python里「萬物都是對象」嘛,如果別人說你根本不會面向對象編程,或者根本不理解面向對象,那可能會得到你的謾罵,那說到底,你真的懂面向對象嗎?試著回答下面幾個問題:
- 面向對象編程的定義是?Python為什麼是面向對象程式語言?Python里萬物都是對象具體的表現形式是什麼?
- 面向對象的特性是哪四點?在Python里這四點都具備嗎?具體是如何實現的?
提示:如果上述的問題回答起來很清晰、很清楚,那本篇文章就可以跳過了,如果感覺思路不清晰,那本篇文章多多少少都會給你程式碼幫助 !
設計模式簡介
在聊面向對象編程之前,先看下設計模式,設計模式主要由編程範式、設計原則、設計模式構成,具體如下圖:
圖裡概念相對較多,但初步掌握,只要有個大概的印象即可。
談談面向對象
面向對象歷史
什麼是面向對象,從歷史說起,我們知道Python正式發布是1991年,Linux正式發布也是1991年,Java正式發布是1995年,Go正式發布是2009年,而面向對象的概念歷史發展是:1960年的simula首次提出類和對象的概念,隨後70年代的程式語言Smalltalk首次用到面向對象概念,可見面向對象概念提出之早,而隨著軟體的發展,後續大多數語言都成了面向對象語言,那面向過程的語言有嗎?有的,C語言就是典型的面向過程語言。
有興趣的可以去讀一讀維基百科,了解下這些語言的發展歷史。
- 面向對象-維基百科
- Python-維基百科
- Java-維基百科
- Linux-維基百科
- Go-維基百科
- …
面向對象概念
面向對象,即object-oriented,在其下又細分為面向對象分析、面向對象設計、面向對象編程,即OOA(Analysis)、OOD(Design)、OOP(programming)。
如果看了維基百科,可能還是很模糊,通過下圖知道關鍵字:編程範式、包含屬性和方法、是類的實例、程式的基本單元、目的是提高軟體的擴展性和靈活性。那一句話就是:面向對象是一種編程範式,以類和對象為基本單元,通過封裝、抽象、多態、繼承這四大特性(不是強要求)來實現程式碼設計,目的是為了提高軟體的可維護性、可擴展性、可復用性。當然上述是我的個人一句話,並不專業,但意思到位即可。
那Python為啥是面向對象程式語言,很明顯,它提供了類和對象這一特性來組織程式碼,同時也具備了四大特性,那自然是。但不具備四大特性一定不是面向對象程式語言嗎?很明顯這不具備參考定義,隨著軟體的發展,很多語言脫離了四大特性,比如Java雖然支援繼承,但不具備多繼承;比如Go直接放棄了繼承這樣的特性,而Java和Go又多出了interface這一介面特性,在Python里則不支援,但它們三者都是面向對象程式語言。
萬物皆對象
我們經常聊Python萬物皆對象,這句話怎麼理解?很簡單,在Python里我們要構造一個類對象的時候,都是以繼承object為前提的,所以判斷「萬物」是不是對象,只要判斷它是不是歸屬於對象即可,這裡的萬物概念很廣,比較常見的以:數字、字元串、布爾、函數為例,那結果如下:
為啥都是對象類型呢?我們再以其中的布爾值為例,通過dir發現其內有大量的屬性和方法(如下圖),那這些方法總不能憑空而來,所以都是繼承來的,接下來就比較清晰了,當我們用變數指代數字、字元串等等時,實際上是構造了一個又一個的對象,這些對象具備的魔法方法使其能支援一系列操作,比如__lt__使其具備了比較小於的能力,比如__eq__使其具備了等等於判斷的能力。
面向對象的特性
關於四大特性:封裝、抽象、繼承、多態,可以看下圖的總結:
Python天然支援四大特性,以前老是對封裝和抽象比較模糊,理解為二者都是封裝抽象公共程式碼,然後提供給其他方法調用,這樣的理解就很片面了,因為二者的意義相差很大。封裝是用於隱藏實現和保護數據,比如Python里我們常在類里定義私有類型來供外部程式調用(如下圖),這裡可以看到a相當於Java的public關鍵字,是允許任意調用;而_a則是Pythoner里約定俗成的私有方法,如果調用pycharm這種ide會用波浪線提示用戶說是不合法的引用;如果是__a,則相當於Java的private,如果外部調用ide會直接標黃表示錯誤。
結果如下:
至於抽象,廣義上的理解即是抽取公共程式碼,對外暴露相應的方法;狹義上的理解就是介面這樣的概念,在介面類里僅包含要暴露的方法,而不透露具體實現,也就是「基於介面而非實現編程」。很可惜,在Python里並不提供介面這一特性,如果你對介面比較模糊的話,可以搜索下介面類 interface,相信會了解到不少資訊。但Python里可以通過duck-typing和抽象基類來額外實現抽象,關於這個後續的文章再詳細介紹了。
另外繼承和多態則是基本語法了,這裡也不細說。
總結
本篇文章就到這了,雖然說得都是基礎,但相信如果你看完了還是會有一些收穫。