前言
學(xué)一門語言貴在堅持用它,不用就淡忘了,而記錄下一篇文章也有助于日后快速回憶。全文分為兩大部分,分別是Python基礎(chǔ)語法和面向?qū)ο蟆?/p>
第一部分%20Python基礎(chǔ)語法
1.%20認(rèn)識Python
1.1%20Python%20簡介
Python%20的創(chuàng)始人為吉多·范羅蘇姆(Guido%20van%20Rossum)。
Python%20的設(shè)計目標(biāo):
一門簡單直觀的語言并與主要競爭者一樣強(qiáng)大 開源,以便任何人都可以為它做貢獻(xiàn)%20代碼像純英語那樣容易理解 適用于短期開發(fā)的日常任務(wù)
Python%20的設(shè)計哲學(xué):
優(yōu)雅、明確、簡單
Python%20開發(fā)者的哲學(xué)是:用一種方法,最好是只有一種方法來做一件事
Python%20是完全面向?qū)ο蟮恼Z言,在%20Python%20中一切皆對象。
可擴(kuò)展性:如果需要一段關(guān)鍵代碼運(yùn)行得更快或者希望某些算法不公開,可以把這部分程序用%20C%20或%20C++%20編寫,然后在%20Python%20程序中使用它們。
1.2.%20第一個Python程序
執(zhí)行%20Python%20程序的三種方式:解釋器、交互式運(yùn)行、IDE運(yùn)行
Python%20是一個格式非常嚴(yán)格的程序設(shè)計語言。python%202.x%20默認(rèn)不支持中文。
ASCII%20字符只包含%20256%20個字符,不支持中文
- Python%202.x%20的解釋器名稱是 python
- Python%203.x%20的解釋器名稱是 python3
為了照顧現(xiàn)有的程序,官方提供了一個過渡版本%20—— Python%202.6。
提示:如果開發(fā)時,無法立即使用%20Python%203.0(還有極少的第三方庫不支持%203.0%20的語法),建議
先使用%20Python%203.0%20版本進(jìn)行開發(fā)%20然后使用%20Python%202.6、Python%202.7%20來執(zhí)行,并且做一些兼容性的處理
IPython%20是一個%20python%20的 交互式%20shell,比默認(rèn)的%20python%20shell%20好用得多,它支持%20bash%20shell%20命令,適合于學(xué)習(xí)/驗證%20Python%20語法或者局部代碼。
集成開發(fā)環(huán)境(IDE,Integrated%20Development%20Environment)—— 集成了開發(fā)軟件需要的所有工具,一般包括以下工具:
- 圖形用戶界面
- 代碼編輯器(支持 代碼補(bǔ)全/自動縮進(jìn))
- 編譯器/解釋器
- 調(diào)試器(斷點/單步執(zhí)行)
- ……
PyCharm 是 Python 的一款非常優(yōu)秀的集成開發(fā)環(huán)境

PyCharm運(yùn)行工具欄
1.3. PyCharm 的設(shè)置
PyCharm 的 配置信息 是保存在 用戶家目錄下 的 .PyCharmxxxx.x 目錄下的,xxxx.x 表示當(dāng)前使用的 PyCharm 的版本號
1.3.1 恢復(fù) PyCharm 的初始設(shè)置:
- 關(guān)閉正在運(yùn)行的 PyCharm
- 在終端中執(zhí)行以下終端命令,刪除 PyCharm 的配置信息目錄:
$ rm -r ~/.PyCharm2016.3
- 重新啟動 PyCharm
1.3.2 PyCharm 安裝和啟動步驟:
- 執(zhí)行以下終端命令,解壓縮下載后的安裝包
$ tar -zxvf pycharm-professional-2017.1.3.tar.gz
- 將解壓縮后的目錄移動到 /opt 目錄下,可以方便其他用戶使用
/opt 目錄用戶存放給主機(jī)額外安裝的軟件
$ sudo mv pycharm-2017.1.3/ /opt/
- 切換工作目錄
$ cd /opt/pycharm-2017.1.3/bin
- 啟動 PyCharm
$ ./pycharm.sh
1.3.3 設(shè)置啟動圖標(biāo)
- 在專業(yè)版中,選擇菜單 Tools / Create Desktop Entry... 可以設(shè)置任務(wù)欄啟動圖標(biāo)
- 注意:設(shè)置圖標(biāo)時,需要勾選 Create the entry for all users
快捷方式文件
/usr/share/Applications/jetbrains-pycharm.desktop
在 ubuntu 中,應(yīng)用程序啟動的快捷方式通常都保存在 /usr/share/applications 目錄下
1.3.4 卸載之前版本的 PyCharm
要卸載 PyCharm 只需要做以下兩步工作:
- 刪除解壓縮目錄
$ sudo rm -r /opt/pycharm-2016.3.1/
- 刪除家目錄下用于保存配置信息的隱藏目錄
$ rm -r ~/.PyCharm2016.3/
如果不再使用 PyCharm 還需要將 /usr/share/applications/ 下的 jetbrains-pycharm.desktop 刪掉
1.4. 多文件項目的演練
- 開發(fā) 項目 就是開發(fā)一個 專門解決一個復(fù)雜業(yè)務(wù)功能的軟件
- 通常每 一個項目 就具有一個 獨(dú)立專屬的目錄,用于保存 所有和項目相關(guān)的文件
- 在 PyCharm 中,要想讓哪一個 Python 程序能夠執(zhí)行,必須首先通過 鼠標(biāo)右鍵的方式執(zhí)行 一下
- 對于初學(xué)者而言,在一個項目中設(shè)置多個程序可以執(zhí)行,是非常方便的,可以方便對不同知識點的練習(xí)和測試
- 對于商業(yè)項目而言,通常在一個項目中,只有一個 可以直接執(zhí)行的 Python 源程序

讓選中的程序可以執(zhí)行
2. 注釋
- 注釋的作用
使用用自己熟悉的語言,在程序中對某些代碼進(jìn)行標(biāo)注說明,增強(qiáng)程序的可讀性
2.1 單行注釋(行注釋)
- 以 # 開頭,# 右邊的所有東西都被當(dāng)做說明文字,而不是真正要執(zhí)行的程序,只起到輔助說明作用
print("hello python") # 輸出 `hello python`
為了保證代碼的可讀性,# 后面建議先添加一個空格,然后再編寫相應(yīng)的說明文字;為了保證代碼的可讀性,注釋和代碼之間 至少要有 兩個空格。
2.2 多行注釋(塊注釋)
- 要在 Python 程序中使用多行注釋,可以用 一對 連續(xù)的 三個 引號(單引號和雙引號都可以)
"""
這是一個多行注釋
在多行注釋之間,可以寫很多很多的內(nèi)容……
"""
print("hello python")
提示:
- 注釋不是越多越好,對于一目了然的代碼,不需要添加注釋
- 對于 復(fù)雜的操作,應(yīng)該在操作開始前寫上若干行注釋
- 對于 不是一目了然的代碼,應(yīng)在其行尾添加注釋(為了提高可讀性,注釋應(yīng)該至少離開代碼 2 個空格)
- 絕不要描述代碼,假設(shè)閱讀代碼的人比你更懂 Python,他只是不知道你的代碼要做什么
2.3 代碼規(guī)范:
- Python 官方提供有一系列 PEP(Python Enhancement Proposals) 文檔,其中第 8 篇文檔專門針對 Python 的代碼格式 給出了建議,也就是俗稱的 PEP 8: 文檔地址:https://www.python.org/dev/peps/pep-0008/ 谷歌有對應(yīng)的中文文檔:http://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/
3. 運(yùn)算符
3.1 算數(shù)運(yùn)算符
是完成基本的算術(shù)運(yùn)算使用的符號,用來處理四則運(yùn)算,而“+”和“*”還可以用來處理字符串。
運(yùn)算符 描述 實例 + 加 10 + 20 = 30 - 減 10 - 20 = -10 * 乘 10 * 20 = 200 / 除 10 / 20 = 0.5 // 取整除 返回除法的整數(shù)部分(商) 9 // 2 輸出結(jié)果 4 % 取余數(shù) 返回除法的余數(shù) 9 % 2 = 1 ** 冪 又稱次方、乘方,2 ** 3 = 8
3.2 比較(關(guān)系)運(yùn)算符
運(yùn)算符 描述 == 檢查兩個操作數(shù)的值是否 相等,如果是,則條件成立,返回 True != 檢查兩個操作數(shù)的值是否 不相等,如果是,則條件成立,返回 True > 檢查左操作數(shù)的值是否 大于右操作數(shù)的值,如果是,則條件成立,返回 True < 檢查左操作數(shù)的值是否 小于 右操作數(shù)的值,如果是,則條件成立,返回 True >= 檢查左操作數(shù)的值是否 大于或等于 右操作數(shù)的值,如果是,則條件成立,返回 True <= 檢查左操作數(shù)的值是否 小于或等于 右操作數(shù)的值,如果是,則條件成立,返回 True
Python 2.x 中判斷 不等于 還可以使用 <> 運(yùn)算符 != 在 Python 2.x 中同樣可以用來判斷 不等于
3.3 賦值運(yùn)算符
- 在 Python 中,使用 = 可以給變量賦值。在算術(shù)運(yùn)算時,為了簡化代碼的編寫,Python 還提供了一系列的 與 算術(shù)運(yùn)算符 對應(yīng)的 賦值運(yùn)算符,注意:賦值運(yùn)算符中間不能使用空格。
運(yùn)算符 描述 實例 = 簡單的賦值運(yùn)算符 c = a + b 將 a + b 的運(yùn)算結(jié)果賦值為 c += 加法賦值運(yùn)算符 c += a 等效于 c = c + a -= 減法賦值運(yùn)算符 c -= a 等效于 c = c - a *= 乘法賦值運(yùn)算符 c *= a 等效于 c = c * a /= 除法賦值運(yùn)算符 c /= a 等效于 c = c / a //= 取整除賦值運(yùn)算符 c //= a 等效于 c = c // a %= 取 模 (余數(shù))賦值運(yùn)算符 c %= a 等效于 c = c % a **= 冪賦值運(yùn)算符 c **= a 等效于 c = c ** a
3.4 身份運(yùn)算符
身份運(yùn)算符比較兩個對象的內(nèi)存位置。常用的有兩個身份運(yùn)算符,如下所述:
運(yùn)算符 描述 示例 is 判斷兩個標(biāo)識符是不是引用同一個對象 x is y,類似 id(x) == id(y) is not 判斷兩個標(biāo)識符是不是引用不同對象 x is not y,類似 id(a) != id(b)
辨析
- is 用于判斷 兩個變量引用的對象是否為同一個
- == 用于判斷 引用變量的值 是否相等
3.5 成員運(yùn)算符
Python成員運(yùn)算符測試給定值是否為序列中的成員。 有兩個成員運(yùn)算符,如下所述:
運(yùn)算符 描述 in 如果在指定的序列中找到一個變量的值,則返回true,否則返回false。 not in 如果在指定序列中找不到變量的值,則返回true,否則返回false。
3.6 邏輯運(yùn)算符
運(yùn)算符 邏輯表達(dá)式 描述 and x and y 只有 x 和 y 的值都為 True,才會返回 True<br />否則只要 x 或者 y 有一個值為 False,就返回 False or x or y 只要 x 或者 y 有一個值為 True,就返回 True<br />只有 x 和 y 的值都為 False,才會返回 False not not x 如果 x 為 True,返回 False<br />如果 x 為 False,返回 True
3.7 運(yùn)算符優(yōu)先級
- 以下表格的算數(shù)優(yōu)先級由高到最低順序排列:
運(yùn)算符 描述 ** 冪 (最高優(yōu)先級) * / % // 乘、除、取余數(shù)、取整除 + - 加法、減法 <= < > >= 比較運(yùn)算符 == != 等于運(yùn)算符 = %= /= //= -= += *= **= 賦值運(yùn)算符 is is not 身份運(yùn)算符 in not in 成員運(yùn)算符 not or and 邏輯運(yùn)算符
<補(bǔ)>程序執(zhí)行原理

Python程序執(zhí)行示意圖
- 操作系統(tǒng)會首先讓 CPU 把 Python 解釋器 的程序復(fù)制到 內(nèi)存 中
- Python 解釋器 根據(jù)語法規(guī)則,從上向下 讓 CPU 翻譯 Python 程序中的代碼
- CPU 負(fù)責(zé)執(zhí)行翻譯完成的代碼
Python 的解釋器有多大?
- 執(zhí)行以下終端命令可以查看 Python 解釋器的大小
看完這篇文章,你的Python基礎(chǔ)就差不多了# 1. 確認(rèn)解釋器所在位置
$ which python
# 2. 查看 python 文件大小(只是一個軟鏈接)
$ ls -lh /usr/bin/python
# 3. 查看具體文件大小
$ ls -lh /usr/bin/python2.7
4. 變量
4.1 變量定義
- 在 Python 中,每個變量 在使用前都必須賦值,變量 賦值以后 改變量 才會被創(chuàng)建
- 可以用 其他變量的計算結(jié)果 來定義變量
- 變量名 只有在 第一次出現(xiàn) 才是 定義變量
變量名 = 值
使用交互式方式,如果要查看變量內(nèi)容,直接輸入變量名即可,不需要使用 print 函數(shù)使用解釋器執(zhí)行,如果要輸出變量的內(nèi)容,必須要要使用 print 函數(shù)
4.2 變量的類型
- 在 Python 中定義變量是 不需要指定類型(在其他很多高級語言中都需要),Python 可以根據(jù) = 等號右側(cè)的值,自動推導(dǎo)出變量中存儲數(shù)據(jù)的類型
- 數(shù)據(jù)類型可以分為 數(shù)字型 和 非數(shù)字型 數(shù)字型 整型 (int):Python3中的所有整數(shù)都表示為長整數(shù)。 因此,長整數(shù)沒有單獨(dú)的數(shù)字類型。 浮點型(float) 布爾型(bool) :真 True 非 0 數(shù) —— 非零即真,假 False 0。 復(fù)數(shù)型 (complex):復(fù)數(shù)是由x + yj表示的有序?qū)Φ膶崝?shù)浮點數(shù)組成,其中x和y是實數(shù),j是虛數(shù)單位。 非數(shù)字型:有些運(yùn)算符還支持這些數(shù)據(jù)類型,詳見4.4.5.3 運(yùn)算符。 字符串(str):加號(+)是字符串連接運(yùn)算符,星號(*)是重復(fù)運(yùn)算符。 列表(list) 元組(tuple) 字典(dict)
提示:在 Python 2.x 中,整數(shù) 根據(jù)保存數(shù)值的長度還分為:
int(整數(shù)) long(長整數(shù))
- 使用 type 函數(shù)可以查看一個變量的類型
In [1]: type(name)
<補(bǔ)>不同類型變量之間的計算
- 數(shù)字型變量 之間可以直接計算
- 在 Python 中,兩個數(shù)字型變量是可以直接進(jìn)行 算數(shù)運(yùn)算的
- 如果變量是 bool 型,在計算時 True 對應(yīng)的數(shù)字是 1 False 對應(yīng)的數(shù)字是 0
- 字符串變量 之間使用 + 拼接字符串
- 字符串變量 可以和 整數(shù) 使用 * 重復(fù)拼接相同的字符串
- 數(shù)字型變量 和 字符串 之間 不能進(jìn)行其他計算
<補(bǔ)>從鍵盤獲取輸入信息:input
- 在 Python 中可以使用 input 函數(shù)從鍵盤等待用戶的輸入
- 用戶輸入的 任何內(nèi)容 Python 都認(rèn)為是一個 字符串
字符串變量 = input("提示信息:")
<補(bǔ)>類型轉(zhuǎn)換函數(shù)
函數(shù) 說明 int(x) 將 x 轉(zhuǎn)換為一個整數(shù) float(x) 將 x 轉(zhuǎn)換到一個浮點數(shù) str(x) 將對象x轉(zhuǎn)換為字符串表示形式 tuple(s) 將s轉(zhuǎn)換為元組 list(s) 將s轉(zhuǎn)換為列表
price = float(input("請輸入價格:"))
<補(bǔ)>格式化輸出:print
- 如果希望輸出文字信息的同時,一起輸出 數(shù)據(jù),就需要使用到 格式化操作符
- % 被稱為 格式化操作符,專門用于處理字符串中的格式 包含 % 的字符串,被稱為 格式化字符串 % 和不同的 字符 連用,不同類型的數(shù)據(jù) 需要使用 不同的格式化字符
格式化字符 含義 %s 字符串 %d 有符號十進(jìn)制整數(shù),%06d 表示輸出的整數(shù)顯示位數(shù),不足的地方使用 0 補(bǔ)全 %f 浮點數(shù),%.2f 表示小數(shù)點后只顯示兩位 %% 輸出 %
- 語法格式如下:
print("格式化字符串" % 變量1)
print("格式化字符串" % (變量1, 變量2...))
4.4.5 公共方法和變量的高級應(yīng)用
4.4.5.1 內(nèi)置函數(shù)
Python 包含了以下內(nèi)置函數(shù):
函數(shù) 描述 備注 len(item) 計算容器中元素個數(shù) del(item) 刪除變量 del 有兩種方式 max(item) 返回容器中元素最大值 如果是字典,只針對 key 比較 min(item) 返回容器中元素最小值 如果是字典,只針對 key 比較 cmp(item1, item2) 比較兩個值,-1 小于 / 0 相等 / 1 大于 Python 3.x 取消了 cmp 函數(shù)
注意:字符串 比較符合以下規(guī)則: "0" < "A" < "a"。
4.4.5.2 切片
描述 Python 表達(dá)式 結(jié)果 支持的數(shù)據(jù)類型 切片 "0123456789"[::-2] "97531" 字符串、列表、元組
- 切片 使用 索引值 來限定范圍,從一個大的 字符串 中 切出 小的 字符串
- 列表 和 元組 都是 有序 的集合,都能夠 通過索引值 獲取到對應(yīng)的數(shù)據(jù)
- 字典 是一個 無序 的集合,是使用 鍵值對 保存數(shù)據(jù)
面向?qū)ο缶幊?—— Object Oriented Programming 簡寫 OOP
- 面向過程 —— 怎么做?
把完成某一個需求的 所有步驟 從頭到尾 逐步實現(xiàn)
根據(jù)開發(fā)需求,將某些 功能獨(dú)立 的代碼 封裝 成一個又一個 函數(shù)
最后完成的代碼,就是順序地調(diào)用 不同的函數(shù)
特點:
注重 步驟與過程,不注重職責(zé)分工
如果需求復(fù)雜,代碼會變得很復(fù)雜
開發(fā)復(fù)雜項目,沒有固定的套路,開發(fā)難度很大! - 面向?qū)ο?—— 誰來做? 相比較函數(shù),面向?qū)ο?是更大的封裝,根據(jù)職責(zé)在 一個對象中封裝多個方法 在完成某一個需求前,首先確定 職責(zé) —— 要做的事情(方法)
根據(jù) 職責(zé) 確定不同的 對象,在 對象 內(nèi)部封裝不同的 方法(多個)
最后完成的代碼,就是順序地讓 不同的對象 調(diào)用 不同的方法
特點:
注重 對象和職責(zé),不同的對象承擔(dān)不同的職責(zé)
更加適合應(yīng)對復(fù)雜的需求變化,是專門應(yīng)對復(fù)雜項目開發(fā),提供的固定套路
需要在面向過程基礎(chǔ)上,再學(xué)習(xí)一些面向?qū)ο蟮恼Z法 - 類和對象
類 是對一群具有 相同 特征 或者 行為 的事物的一個統(tǒng)稱,是抽象的,特征 被稱為 屬性,行為 被稱為 方法。
對象 是 由類創(chuàng)建出來的一個具體存在,是類的實例化。
在程序開發(fā)中,要設(shè)計一個類,通常需要滿足一下三個要素: 類名 這類事物的名字,滿足大駝峰命名法 屬性 這類事物具有什么樣的特征 方法 這類事物具有什么樣的行為
2. 面向?qū)ο蠡A(chǔ)語法
2.1 dir 內(nèi)置函數(shù)和內(nèi)置方法
在 Python 中 對象幾乎是無所不在的,我們之前學(xué)習(xí)的 變量、數(shù)據(jù)、函數(shù) 都是對象。在 Python 中可以使用以下兩個方法驗證:
- 在 標(biāo)識符 / 數(shù)據(jù) 后輸入一個點 .,然后按下 TAB 鍵,iPython 會提示該對象能夠調(diào)用的方法列表。
- 使用內(nèi)置函數(shù) dir 傳入 標(biāo)識符 / 數(shù)據(jù),可以查看對象內(nèi)的 所有屬性及方法。
提示__方法名__格式的方法是 Python 提供的 內(nèi)置方法 / 屬性。
序號 方法名 類型 作用 01 __new__ 方法 創(chuàng)建對象時,會被 自動 調(diào)用 02 __init__ 方法 對象被初始化時,會被 自動 調(diào)用 03 __del__ 方法 對象被從內(nèi)存中銷毀前,會被 自動 調(diào)用 04 __str__ 方法 返回對象的描述信息,print 函數(shù)輸出使用
提示 利用好 dir() 函數(shù),在學(xué)習(xí)時很多內(nèi)容就不需要死記硬背了。
2.2 定義簡單的類(只包含方法)
面向?qū)ο笫歉蟮姆庋b,在 一個類中封裝多個方法,這樣通過這個類創(chuàng)建出來的對象,就可以直接調(diào)用這些方法了!
定義一個只包含方法的類:
class 類名:
def 方法1(self, 參數(shù)列表):
pass
def 方法2(self, 參數(shù)列表):
pass
方法 的定義格式和之前學(xué)習(xí)過的函數(shù)幾乎一樣,區(qū)別在于第一個參數(shù)必須是 self。注意:類名的 命名規(guī)則 要符合 大駝峰命名法。當(dāng)一個類定義完成之后,要使用這個類來創(chuàng)建對象,語法格式如下:
對象變量 = 類名()
在面向?qū)ο箝_發(fā)中,引用的概念是同樣適用的!
使用 print輸出 對象變量,默認(rèn)情況下,是能夠輸出這個變量 引用的對象 是 由哪一個類創(chuàng)建的對象,以及 在內(nèi)存中的地址(十六進(jìn)制表示)。
提示:在計算機(jī)中,通常使用 十六進(jìn)制 表示 內(nèi)存地址。
如果在開發(fā)中,希望使用 print輸出 對象變量 時,能夠打印 自定義的內(nèi)容,就可以利用 __str__這個內(nèi)置方法了:
class Cat:
def __init__(self, new_name):
self.name = new_name
print("%s 來了" % self.name)
def __del__(self):
print("%s 去了" % self.name)
def __str__(self):
return "我是小貓:%s" % self.name
tom = Cat("Tom")
print(tom)
注意:__str__方法必須返回一個字符串。
2.3 方法中的 self 參數(shù)
在 Python 中,要 給對象設(shè)置屬性,非常的容易,只需要在 類的外部的代碼 中直接通過 對象.設(shè)置一個屬性即可,但是不推薦使用:
看完這篇文章,你的Python基礎(chǔ)就差不多了class Cat:
"""這是一個貓類"""
def eat(self):
print("小貓愛吃魚")
def drink(self):
print("小貓在喝水")
tom = Cat()
# 給對象設(shè)置屬性
tom.name = "Tom"
因為:對象屬性的封裝應(yīng)該封裝在類的內(nèi)部
由哪一個對象調(diào)用的方法,方法內(nèi)的 self就是哪一個對象的引用
- 在類封裝的方法內(nèi)部,self 就表示當(dāng)前調(diào)用方法的對象自己,在方法內(nèi)部:
可以通過 self.訪問對象的屬性,也可以通過 self.調(diào)用對象的其他方法。 - 調(diào)用方法時,程序員不需要傳遞 self 參數(shù)。
- 在 類的外部,通過變量名.訪問對象的 屬性和方法
在 類封裝的方法中,通過 self.訪問對象的 屬性和方法
2.4 初始化方法:__init__
- 當(dāng)使用 類名() 創(chuàng)建對象時,會 自動 執(zhí)行以下操作:
為對象在內(nèi)存中分配空間 —— 創(chuàng)建對象
為對象的屬性設(shè)置初始值 —— 初始化方法(__init__)
__init__ 方法是 專門 用來定義一個類具有哪些屬性的方法!
- 在 __init__ 方法內(nèi)部使用 self.屬性名 = 屬性的初始值 就可以定義屬性,定義屬性之后,再使用 類創(chuàng)建的對象,都會擁有該屬性。
- 在開發(fā)中,如果希望在 創(chuàng)建對象的同時,就設(shè)置對象的屬性,可以對 __init__ 方法進(jìn)行 改造: 把希望設(shè)置的屬性值,定義成 __init__方法的參數(shù) 在方法內(nèi)部使用 self.屬性 = 形參 接收外部傳遞的參數(shù) 在創(chuàng)建對象時,使用 類名(屬性1, 屬性2...) 調(diào)用
class Cat:
def __init__(self, name):
print("初始化方法 %s" % name)
self.name = name
...
tom = Cat("Tom")
...
lazy_cat = Cat("大懶貓")
...
2.5 私有屬性和私有方法
應(yīng)用場景
- 在實際開發(fā)中,對象 的 某些屬性或方法 可能只希望 在對象的內(nèi)部被使用,而 不希望在外部被訪問到
- 私有屬性 就是 對象 不希望公開的 屬性
- 私有方法 就是 對象 不希望公開的 方法
定義方式
- 在 定義屬性或方法時,在 屬性名或者方法名前 增加 兩個下劃線,定義的就是 私有屬性或方法:

私有屬性和私有方法
偽私有屬性和私有方法Python 中,并沒有 真正意義 的 私有在給 屬性、方法 命名時,實際是對名稱做了一些特殊處理,使得外界無法訪問到處理方式:在 名稱 前面加上_類名 => _類名__名稱
# 私有屬性,外部不能直接訪問到
print(xiaofang._Women__age)
# 私有方法,外部不能直接調(diào)用
xiaofang._Women__secret()
提示:在日常開發(fā)中,不要使用這種方式,訪問對象的 私有屬性 或 私有方法。
3. 封裝、繼承和多態(tài)
面向?qū)ο笕筇匦裕?/p>
- 封裝 根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個抽象的 類 中
- 繼承 實現(xiàn)代碼的重用,相同的代碼不需要重復(fù)的編寫
- 多態(tài) 不同的對象調(diào)用相同的方法,產(chǎn)生不同的執(zhí)行結(jié)果,增加代碼的靈活度
3.1 繼承
3.1.1 單繼承
繼承的概念:子類 擁有 父類 以及 父類的父類 中封裝的所有 屬性 和 方法。
class 類名(父類名):
pass
當(dāng) 父類 的方法實現(xiàn)不能滿足子類需求時,可以對方法進(jìn)行重寫(override)重寫 父類方法有兩種情況:
- 覆蓋 父類的方法:父類的方法實現(xiàn) 和 子類的方法實現(xiàn)完全不同
具體的實現(xiàn)方式,就相當(dāng)于在 子類中 定義了一個 和父類同名的方法并且實現(xiàn)。 - 對父類方法進(jìn)行 擴(kuò)展:子類的方法實現(xiàn) 中 包含 父類的方法實現(xiàn)
在子類中 重寫 父類的方法;在需要的位置使用 super().父類方法 來調(diào)用父類方法的執(zhí)行代碼;其他的位置針對子類的需求,編寫 子類特有的代碼實現(xiàn)。
關(guān)于 super
- 在 Python 中 super 是一個 特殊的類
- super()就是使用 super 類創(chuàng)建出來的對象
- 最常 使用的場景就是在 重寫父類方法時,調(diào)用 在父類中封裝的方法實現(xiàn)
調(diào)用父類方法的另外一種方式:在 Python 2.x 時,如果需要調(diào)用父類的方法,還可以使用以下方式:父類名.方法(self)。目前在 Python 3.x 還支持這種方式,但不推薦使用,因為一旦 父類發(fā)生變化,方法調(diào)用位置的 類名 同樣需要修改。
父類的 私有屬性 和 私有方法
子類對象 不能 在自己的方法內(nèi)部,直接 訪問 父類的 私有屬性 或 私有方法子類對象 可以通過 父類 的 公有方法 間接 訪問到 私有屬性 或 私有方法
私有屬性、方法 是對象的隱私,不對外公開,外界 以及 子類 都不能直接訪問 私有屬性、方法 通常用于做一些內(nèi)部的事情
3.1.2 多繼承
子類 可以擁有 多個父類,并且具有 所有父類 的 屬性 和 方法,例如:孩子 會繼承自己 父親 和 母親 的 特性。
class 子類名(父類名1, 父類名2...):
pass
Python 中的 MRO算法(Method Resolution Order)
- 如果 不同的父類 中存在 同名的方法,子類對象 在調(diào)用方法時,會調(diào)用 哪一個父類中的方法呢?
提示:開發(fā)時,應(yīng)該盡量避免這種容易產(chǎn)生混淆的情況! —— 如果 父類之間 存在 同名的屬性或者方法,應(yīng)該 盡量避免使用多繼承。 - Python 中針對 類 提供了一個 內(nèi)置屬性__mro__ 可以查看 方法 搜索順序 在搜索方法時,是按照 mro 的輸出結(jié)果 從左至右 的順序查找的 如果在當(dāng)前類中 找到方法,就直接執(zhí)行,不再搜索 如果 沒有找到,就查找下一個類 中是否有對應(yīng)的方法,如果找到,就直接執(zhí)行,不再搜索 如果找到最后一個類,還沒有找到方法,程序報錯
MRO 是 method resolution order —— 方法搜索順序,主要用于 在多繼承時判斷 方法、屬性 的調(diào)用 路徑
新式類與舊式(經(jīng)典)類
- 新式類:以 object 為基類的類,推薦使用
- 經(jīng)典類:不以 object為基類的類,不推薦使用
在 Python 3.x 中定義類時,如果沒有指定父類,會 默認(rèn)使用 object作為該類的 基類 —— Python 3.x 中定義的類都是 新式類,在 Python 2.x 中定義類時,如果沒有指定父類,則不會以 object 作為 基類。
- 為了保證編寫的代碼能夠同時在 Python 2.x 和 Python 3.x 運(yùn)行!今后在定義類時,如果沒有父類,建議統(tǒng)一繼承自 object:
class 類名(object):
pass
object 是 Python 為所有對象提供的 基類,提供有一些內(nèi)置的屬性和方法,可以使用 dir(object) 函數(shù)查看。
3.2 多態(tài)
面向?qū)ο笕筇匦裕?/p>
- 封裝 根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個抽象的 類 中 定義類的準(zhǔn)則
- 繼承 實現(xiàn)代碼的重用,相同的代碼不需要重復(fù)的編寫 設(shè)計類的技巧 子類針對自己特有的需求,編寫特定的代碼
- 多態(tài) 不同的 子類對象 調(diào)用相同的 父類方法,產(chǎn)生不同的執(zhí)行結(jié)果 增加代碼的靈活度 以 繼承 和 重寫父類方法 為前提 調(diào)用方法的技巧,不會影響到類的內(nèi)部設(shè)計
多態(tài) 更容易編寫出出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化!
案例:在 Dog 類中封裝方法 game:普通狗只是簡單的玩耍定義 XiaoTianDog 繼承自 Dog,并且重寫 game 方法:哮天犬需要在天上玩耍定義 Person 類,并且封裝一個 和狗玩 的方法:在方法內(nèi)部,直接讓 狗對象 調(diào)用 game 方法

多態(tài)示例
Person 類中只需要讓 狗對象 調(diào)用 game 方法,而不關(guān)心具體是 什么狗。
4. 類屬性和類方法
4.1 類的結(jié)構(gòu)
通常會把:創(chuàng)建出來的 對象 叫做 類的實例創(chuàng)建對象的 動作 叫做 實例化對象的屬性 叫做 實例屬性對象調(diào)用的方法 叫做 實例方法每一個對象 都有自己獨(dú)立的內(nèi)存空間,保存各自不同的屬性多個對象的方法,在內(nèi)存中只有一份,在調(diào)用方法時,需要把對象的引用傳遞到方法內(nèi)部

各個不同的屬性,獨(dú)一份的方法
在 Python 中,類是一個特殊的對象。
Python 中 一切皆對象:
class AAA: 定義的類屬于 類對象 obj1 = AAA() 屬于 實例對象
在程序運(yùn)行時,類同樣會被加載到內(nèi)存在程序運(yùn)行時,類對象在內(nèi)存中只有一份,使用 一個類可以創(chuàng)建出很多個對象實例除了封裝實例的屬性和方法外,類對象還可以擁有自己的屬性和方法——類屬性、類方法,通過 類名. 的方式可以 訪問類的屬性 或者 調(diào)用類的方法

類的結(jié)構(gòu)
4.2 類屬性和實例屬性
類屬性 就是 類對象中定義的屬性通常用來記錄與這個類相關(guān)的特征類屬性不會用于記錄具體對象的特征示例:定義一個 工具類,每件工具都有自己的 name:需求 —— 知道使用這個類,創(chuàng)建了多少個工具對象?

屬性的獲取機(jī)制
在 Python 中 屬性的獲取 存在一個 向上查找機(jī)制

因此,要訪問類屬性有兩種方式:
- 類名.類屬性
- 對象.類屬性 (不推薦,因為如果使用 對象.類屬性 = 值 賦值語句,只會給對象添加一個屬性,而不會影響到類屬性的值)
4.3 類方法和靜態(tài)方法
4.3.1 類方法
- 類屬性 就是針對 類對象 定義的屬性 使用 賦值語句 在 class 關(guān)鍵字下方可以定義 類屬性 類屬性 用于記錄 與這個類相關(guān) 的特征
- 類方法 就是針對 類對象 定義的方法 在 類方法 內(nèi)部可以直接訪問 類屬性 或者調(diào)用其他的 類方法
語法如下
@classmethod
def 類方法名(cls):
pass
- 類方法需要用 修飾器 @classmethod 來標(biāo)識,告訴解釋器這是一個類方法
- 類方法的 第一個參數(shù) 應(yīng)該是 cls 由 哪一個類 調(diào)用的方法,方法內(nèi)的 cls 就是 哪一個類的引用 這個參數(shù)和 實例方法 的第一個參數(shù)是 self 類似 提示 使用其他名稱也可以,不過習(xí)慣使用 cls
- 通過 類名. 調(diào)用 類方法,調(diào)用方法時,不需要傳遞 cls 參數(shù)
- 在方法內(nèi)部 可以通過 cls. 訪問類的屬性 也可以通過 cls. 調(diào)用其他的類方法
示例
- 定義一個 工具類,每件工具都有自己的 name
- 需求 —— 在 類 封裝一個 show_tool_count 的類方法,輸出使用當(dāng)前這個類,創(chuàng)建的對象個數(shù)
@classmethod
def show_tool_count(cls):
"""顯示工具對象的總數(shù)"""
print("工具對象的總數(shù) %d" % cls.count)
4.3.2 靜態(tài)方法
- 在開發(fā)時,如果需要在 類 中封裝一個方法,這個方法: 既 不需要 訪問 實例屬性 或者調(diào)用 實例方法 也 不需要 訪問 類屬性 或者調(diào)用 類方法
- 這個時候,可以把這個方法封裝成一個 靜態(tài)方法
語法如下
@staticmethod
def 靜態(tài)方法名():
pass
- 靜態(tài)方法 需要用 修飾器 @staticmethod 來標(biāo)識,告訴解釋器這是一個靜態(tài)方法
- 通過 類名. 調(diào)用 靜態(tài)方法
示例:
- 靜態(tài)方法 show_help 顯示游戲幫助信息
- 類方法 show_top_score 顯示歷史最高分
- 實例方法 start_game 開始當(dāng)前玩家的游戲

探索:
- 實例方法 —— 方法內(nèi)部需要訪問 實例屬性 實例方法 內(nèi)部可以使用 類名. 訪問類屬性
- 類方法 —— 方法內(nèi)部 只需要訪問 類屬性
- 靜態(tài)方法 —— 方法內(nèi)部,不需要訪問 實例屬性 和 類屬性
5. 單例
5.1 單例設(shè)計模式
- 設(shè)計模式 設(shè)計模式 是 前人工作的總結(jié)和提煉,通常,被人們廣泛流傳的設(shè)計模式都是針對 某一特定問題 的成熟的解決方案 使用 設(shè)計模式 是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
- 單例設(shè)計模式 目的 —— 讓 類 創(chuàng)建的對象,在系統(tǒng)中 只有 唯一的一個實例 每一次執(zhí)行 類名() 返回的對象,內(nèi)存地址是相同的
- 單例設(shè)計模式的應(yīng)用場景 音樂播放 對象 回收站 對象 打印機(jī) 對象 ……
5.2 靜態(tài)方法: __new__
- 使用 類名() 創(chuàng)建對象時,Python 的解釋器 首先 會 調(diào)用 __new__ 方法為對象 分配空間
- __new__ 是一個 由 object 基類提供的 內(nèi)置的靜態(tài)方法,主要作用有兩個: 在內(nèi)存中為對象 分配空間 返回 對象的引用
- Python 的解釋器獲得對象的 引用 后,將引用作為 第一個參數(shù),傳遞給 __init__ 方法
重寫 __new__ 方法 的代碼非常固定!
- 重寫 __new__ 方法 一定要 return super().__new__(cls),否則 Python 的解釋器 得不到 分配了空間的 對象引用,就不會調(diào)用對象的初始化方法
- 注意:__new__ 是一個靜態(tài)方法,在調(diào)用時需要 主動傳遞 cls 參數(shù)


5.3 Python 中的單例
- 單例 —— 讓 類 創(chuàng)建的對象,在系統(tǒng)中 只有 唯一的一個實例 定義一個 類屬性,初始值是 None,用于記錄 單例對象的引用 重寫 __new__ 方法 如果 類屬性 is None,調(diào)用父類方法分配空間,并在類屬性中記錄結(jié)果 返回 類屬性 中記錄的 對象引用


只執(zhí)行一次初始化工作
- 在每次使用 類名() 創(chuàng)建對象時,Python 的解釋器都會自動調(diào)用兩個方法: __new__ 分配空間 __init__ 對象初始化
- 在對 __new__ 方法改造之后,每次都會得到 第一次被創(chuàng)建對象的引用
- 但是:初始化方法還會被再次調(diào)用
需求
- 讓 初始化動作 只被 執(zhí)行一次
解決辦法
- 定義一個類屬性 init_flag 標(biāo)記是否 執(zhí)行過初始化動作,初始值為 False
- 在 __init__ 方法中,判斷 init_flag,如果為 False 就執(zhí)行初始化動作
- 然后將 init_flag 設(shè)置為 True
- 這樣,再次 自動 調(diào)用 __init__ 方法時,初始化動作就不會被再次執(zhí)行 了

Tips
1、Python 能夠自動的將一對括號內(nèi)部的代碼連接在一起:
'''
**需求**
* 定義 `input_password` 函數(shù),提示用戶輸入密碼
* 如果用戶輸入長度 < 8,拋出異常
* 如果用戶輸入長度 >=8,返回輸入的密碼
'''
def input_password():
# 1. 提示用戶輸入密碼
pwd = input("請輸入密碼:")
# 2. 判斷密碼長度,如果長度 >= 8,返回用戶輸入的密碼
if len(pwd) >= 8:
return pwd
# 3. 密碼長度不夠,需要拋出異常
# 1> 創(chuàng)建異常對象 - 使用異常的錯誤信息字符串作為參數(shù)
ex = Exception("密碼長度不夠")
# 2> 拋出異常對象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print("發(fā)現(xiàn)錯誤:%s" % result)
2、一個對象的 屬性 可以是 另外一個類創(chuàng)建的對象。3、在__init__方法中定義類的屬性時,如果 不知道設(shè)置什么初始值,可以設(shè)置為 None):None 關(guān)鍵字 表示 什么都沒有,表示一個 空對象,沒有方法和屬性,是一個特殊的常量。可以將 None 賦值給任何一個變量。
在 Python 中針對 None 比較時,建議使用is 判斷
4、eval() 函數(shù)十分強(qiáng)大 —— 將字符串 當(dāng)成 有效的表達(dá)式 來求值 并 返回計算結(jié)果

在開發(fā)時千萬不要使用 eval 直接轉(zhuǎn)換 input 的結(jié)果,舉個例子:
看完這篇文章,你的Python基礎(chǔ)就差不多了__import__('os').system('ls')
# 等價代碼
import os
os.system("終端命令")