看完這篇文章,你的Python基礎(chǔ)就差不多了
掃描二維碼
隨時(shí)隨地手機(jī)看文章
來源 :筑夢編程
前言
學(xué)一門語言貴在堅(jiān)持用它,不用就淡忘了,而記錄下一篇文章也有助于日后快速回憶。全文分為兩大部分,分別是Python基礎(chǔ)語法和面向?qū)ο蟆?/p>
第一部分 Python基礎(chǔ)語法
第一部分 Python基礎(chǔ)語法
1. 認(rèn)識Python
1.1 Python 簡介
Python 的創(chuàng)始人為吉多·范羅蘇姆(Guido van Rossum)。
Python 的設(shè)計(jì)目標(biāo):
一門簡單直觀的語言并與主要競爭者一樣強(qiáng)大 開源,以便任何人都可以為它做貢獻(xiàn) 代碼像純英語那樣容易理解 適用于短期開發(fā)的日常任務(wù)
Python 的設(shè)計(jì)哲學(xué):
優(yōu)雅、明確、簡單
Python 開發(fā)者的哲學(xué)是:用一種方法,最好是只有一種方法來做一件事
Python 是完全面向?qū)ο蟮恼Z言,在 Python 中一切皆對象。
可擴(kuò)展性:如果需要一段關(guān)鍵代碼運(yùn)行得更快或者希望某些算法不公開,可以把這部分程序用 C 或 C++ 編寫,然后在 Python 程序中使用它們。
1.2. 第一個(gè)Python程序
執(zhí)行 Python 程序的三種方式:解釋器、交互式運(yùn)行、IDE運(yùn)行
Python 是一個(gè)格式非常嚴(yán)格的程序設(shè)計(jì)語言。python 2.x 默認(rèn)不支持中文。
ASCII 字符只包含 256 個(gè)字符,不支持中文
Python 2.x 的解釋器名稱是 python
Python 3.x 的解釋器名稱是 python3
為了照顧現(xiàn)有的程序,官方提供了一個(gè)過渡版本 —— Python 2.6。
提示:如果開發(fā)時(shí),無法立即使用 Python 3.0(還有極少的第三方庫不支持 3.0 的語法),建議
先使用 Python 3.0 版本進(jìn)行開發(fā) 然后使用 Python 2.6、Python 2.7 來執(zhí)行,并且做一些兼容性的處理
IPython 是一個(gè) python 的 交互式 shell,比默認(rèn)的 python shell 好用得多,它支持 bash shell 命令,適合于學(xué)習(xí)/驗(yàn)證 Python 語法或者局部代碼。
集成開發(fā)環(huán)境(IDE,Integrated Development Environment)—— 集成了開發(fā)軟件需要的所有工具,一般包括以下工具:
圖形用戶界面
代碼編輯器(支持 代碼補(bǔ)全/自動(dòng)縮進(jìn))
編譯器/解釋器
調(diào)試器(斷點(diǎn)/單步執(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
重新啟動(dòng) PyCharm
1.3.2 PyCharm 安裝和啟動(dòng)步驟:
執(zhí)行以下終端命令,解壓縮下載后的安裝包
$ tar -zxvf pycharm-professional-2017.1.3.tar.gz
將解壓縮后的目錄移動(dòng)到 /opt 目錄下,可以方便其他用戶使用
/opt 目錄用戶存放給主機(jī)額外安裝的軟件
$ sudo mv pycharm-2017.1.3/ /opt/
切換工作目錄
$ cd /opt/pycharm-2017.1.3/bin
啟動(dòng) PyCharm
$ ./pycharm.sh
1.3.3 設(shè)置啟動(dòng)圖標(biāo)
在專業(yè)版中,選擇菜單 Tools / Create Desktop Entry... 可以設(shè)置任務(wù)欄啟動(dòng)圖標(biāo)
注意:設(shè)置圖標(biāo)時(shí),需要勾選 Create the entry for all users
快捷方式文件
/usr/share/applications/jetbrains-pycharm.desktop
在 ubuntu 中,應(yīng)用程序啟動(dò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. 多文件項(xiàng)目的演練
開發(fā) 項(xiàng)目 就是開發(fā)一個(gè) 專門解決一個(gè)復(fù)雜業(yè)務(wù)功能的軟件
通常每 一個(gè)項(xiàng)目 就具有一個(gè) 獨(dú)立專屬的目錄,用于保存 所有和項(xiàng)目相關(guān)的文件
在 PyCharm 中,要想讓哪一個(gè) Python 程序能夠執(zhí)行,必須首先通過 鼠標(biāo)右鍵的方式執(zhí)行 一下
對于初學(xué)者而言,在一個(gè)項(xiàng)目中設(shè)置多個(gè)程序可以執(zhí)行,是非常方便的,可以方便對不同知識點(diǎn)的練習(xí)和測試
對于商業(yè)項(xiàng)目而言,通常在一個(gè)項(xiàng)目中,只有一個(gè) 可以直接執(zhí)行的 Python 源程序
讓選中的程序可以執(zhí)行
2. 注釋
注釋的作用
使用用自己熟悉的語言,在程序中對某些代碼進(jìn)行標(biāo)注說明,增強(qiáng)程序的可讀性
2.1 單行注釋(行注釋)
以 # 開頭,# 右邊的所有東西都被當(dāng)做說明文字,而不是真正要執(zhí)行的程序,只起到輔助說明作用
print("hello python") # 輸出 `hello python`
為了保證代碼的可讀性,# 后面建議先添加一個(gè)空格,然后再編寫相應(yīng)的說明文字;為了保證代碼的可讀性,注釋和代碼之間 至少要有 兩個(gè)空格。
2.2 多行注釋(塊注釋)
要在 Python 程序中使用多行注釋,可以用 一對 連續(xù)的 三個(gè) 引號(單引號和雙引號都可以)
"""
這是一個(gè)多行注釋
在多行注釋之間,可以寫很多很多的內(nèi)容……
"""
print("hello python")
提示:
注釋不是越多越好,對于一目了然的代碼,不需要添加注釋
對于 復(fù)雜的操作,應(yīng)該在操作開始前寫上若干行注釋
對于 不是一目了然的代碼,應(yīng)在其行尾添加注釋(為了提高可讀性,注釋應(yīng)該至少離開代碼 2 個(gè)空格)
絕不要描述代碼,假設(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)算符 描述 實(shí)例 + 加 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)算符 描述 == 檢查兩個(gè)操作數(shù)的值是否 相等,如果是,則條件成立,返回 True != 檢查兩個(gè)操作數(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)算時(shí),為了簡化代碼的編寫,Python 還提供了一系列的 與 算術(shù)運(yùn)算符 對應(yīng)的 賦值運(yùn)算符,注意:賦值運(yùn)算符中間不能使用空格。
運(yùn)算符 描述 實(shí)例 = 簡單的賦值運(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)算符比較兩個(gè)對象的內(nèi)存位置。常用的有兩個(gè)身份運(yùn)算符,如下所述:
運(yùn)算符 描述 示例 is 判斷兩個(gè)標(biāo)識符是不是引用同一個(gè)對象 x is y,類似 id(x) == id(y) is not 判斷兩個(gè)標(biāo)識符是不是引用不同對象 x is not y,類似 id(a) != id(b)
辨析
is 用于判斷 兩個(gè)變量引用的對象是否為同一個(gè)
== 用于判斷 引用變量的值 是否相等
3.5 成員運(yùn)算符
Python成員運(yùn)算符測試給定值是否為序列中的成員。有兩個(gè)成員運(yùn)算符,如下所述:
運(yùn)算符 描述 in 如果在指定的序列中找到一個(gè)變量的值,則返回true,否則返回false。not in 如果在指定序列中找不到變量的值,則返回true,否則返回false。
3.6 邏輯運(yùn)算符
運(yùn)算符 邏輯表達(dá)式 描述 and x and y 只有 x 和 y 的值都為 True,才會返回 True<br />否則只要 x 或者 y 有一個(gè)值為 False,就返回 False or x or y 只要 x 或者 y 有一個(gè)值為 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 解釋器的大小
# 1. 確認(rèn)解釋器所在位置
$ which python
# 2. 查看 python 文件大小(只是一個(gè)軟鏈接)
$ ls -lh /usr/bin/python
# 3. 查看具體文件大小
$ ls -lh /usr/bin/python2.7
4. 變量
4.1 變量定義
在 Python 中,每個(gè)變量 在使用前都必須賦值,變量 賦值以后 該變量 才會被創(chuàng)建
可以用 其他變量的計(jì)算結(jié)果 來定義變量
變量名 只有在 第一次出現(xiàn) 才是 定義變量
變量名 = 值
使用交互式方式,如果要查看變量內(nèi)容,直接輸入變量名即可,不需要使用 print 函數(shù)使用解釋器執(zhí)行,如果要輸出變量的內(nèi)容,必須要要使用 print 函數(shù)
4.2 變量的類型
在 Python 中定義變量是 不需要指定類型(在其他很多高級語言中都需要),Python 可以根據(jù) = 等號右側(cè)的值,自動(dòng)推導(dǎo)出變量中存儲數(shù)據(jù)的類型
數(shù)據(jù)類型可以分為 數(shù)字型 和 非數(shù)字型 數(shù)字型 整型 (int):Python3中的所有整數(shù)都表示為長整數(shù)。因此,長整數(shù)沒有單獨(dú)的數(shù)字類型。浮點(diǎn)型(float) 布爾型(bool) :真 True 非 0 數(shù) —— 非零即真,假 False 0。復(fù)數(shù)型 (complex):復(fù)數(shù)是由x + yj表示的有序?qū)Φ膶?shí)數(shù)浮點(diǎn)數(shù)組成,其中x和y是實(shí)數(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ù)可以查看一個(gè)變量的類型
In [1]: type(name)
<補(bǔ)>不同類型變量之間的計(jì)算
數(shù)字型變量 之間可以直接計(jì)算
在 Python 中,兩個(gè)數(shù)字型變量是可以直接進(jìn)行 算數(shù)運(yùn)算的
如果變量是 bool 型,在計(jì)算時(shí) True 對應(yīng)的數(shù)字是 1 False 對應(yīng)的數(shù)字是 0
字符串變量 之間使用 + 拼接字符串
字符串變量 可以和 整數(shù) 使用 * 重復(fù)拼接相同的字符串
數(shù)字型變量 和 字符串 之間 不能進(jìn)行其他計(jì)算
<補(bǔ)>從鍵盤獲取輸入信息:input
在 Python 中可以使用 input 函數(shù)從鍵盤等待用戶的輸入
用戶輸入的 任何內(nèi)容 Python 都認(rèn)為是一個(gè) 字符串
字符串變量 = input("提示信息:")
<補(bǔ)>類型轉(zhuǎn)換函數(shù)
函數(shù) 說明 int(x) 將 x 轉(zhuǎn)換為一個(gè)整數(shù) float(x) 將 x 轉(zhuǎn)換到一個(gè)浮點(diǎn)數(shù) str(x) 將對象x轉(zhuǎn)換為字符串表示形式 tuple(s) 將s轉(zhuǎn)換為元組 list(s) 將s轉(zhuǎn)換為列表
price = float(input("請輸入價(jià)格:"))
<補(bǔ)>格式化輸出:print
如果希望輸出文字信息的同時(shí),一起輸出 數(shù)據(jù),就需要使用到 格式化操作符
% 被稱為 格式化操作符,專門用于處理字符串中的格式 包含 % 的字符串,被稱為 格式化字符串 % 和不同的 字符 連用,不同類型的數(shù)據(jù) 需要使用 不同的格式化字符
格式化字符 含義 %s 字符串 %d 有符號十進(jìn)制整數(shù),%06d 表示輸出的整數(shù)顯示位數(shù),不足的地方使用 0 補(bǔ)全 %f 浮點(diǎn)數(shù),%.2f 表示小數(shù)點(diǎn)后只顯示兩位 %% 輸出 %
語法格式如下:
print("格式化字符串" % 變量1)
print("格式化字符串" % (變量1, 變量2...))
4.4.5 公共方法和變量的高級應(yīng)用
4.4.5.1 內(nèi)置函數(shù)
Python 包含了以下內(nèi)置函數(shù):
函數(shù) 描述 備注 len(item) 計(jì)算容器中元素個(gè)數(shù) del(item) 刪除變量 del 有兩種方式 max(item) 返回容器中元素最大值 如果是字典,只針對 key 比較 min(item) 返回容器中元素最小值 如果是字典,只針對 key 比較 cmp(item1, item2) 比較兩個(gè)值,-1 小于 / 0 相等 / 1 大于 Python 3.x 取消了 cmp 函數(shù)
注意:字符串 比較符合以下規(guī)則:"0" < "A" < "a"。
4.4.5.2 切片
描述 Python 表達(dá)式 結(jié)果 支持的數(shù)據(jù)類型 切片 "0123456789"[::-2] "97531" 字符串、列表、元組
切片 使用 索引值 來限定范圍,從一個(gè)大的 字符串 中 切出 小的 字符串
列表 和 元組 都是 有序 的集合,都能夠 通過索引值 獲取到對應(yīng)的數(shù)據(jù)
字典 是一個(gè) 無序 的集合,是使用 鍵值對 保存數(shù)據(jù)
面向?qū)ο缶幊?—— Object Oriented Programming 簡寫 OOP
面向過程 —— 怎么做?
把完成某一個(gè)需求的 所有步驟 從頭到尾 逐步實(shí)現(xiàn)
根據(jù)開發(fā)需求,將某些 功能獨(dú)立 的代碼 封裝 成一個(gè)又一個(gè) 函數(shù)
最后完成的代碼,就是順序地調(diào)用 不同的函數(shù)
特點(diǎn):
注重 步驟與過程,不注重職責(zé)分工
如果需求復(fù)雜,代碼會變得很復(fù)雜
開發(fā)復(fù)雜項(xiàng)目,沒有固定的套路,開發(fā)難度很大!面向?qū)ο?—— 誰來做?相比較函數(shù),面向?qū)ο?是更大的封裝,根據(jù)職責(zé)在 一個(gè)對象中封裝多個(gè)方法 在完成某一個(gè)需求前,首先確定 職責(zé) —— 要做的事情(方法)
根據(jù) 職責(zé) 確定不同的 對象,在 對象 內(nèi)部封裝不同的 方法(多個(gè))
最后完成的代碼,就是順序地讓 不同的對象 調(diào)用 不同的方法
特點(diǎn):
注重 對象和職責(zé),不同的對象承擔(dān)不同的職責(zé)
更加適合應(yīng)對復(fù)雜的需求變化,是專門應(yīng)對復(fù)雜項(xiàng)目開發(fā),提供的固定套路
需要在面向過程基礎(chǔ)上,再學(xué)習(xí)一些面向?qū)ο蟮恼Z法類和對象
類 是對一群具有 相同 特征 或者 行為 的事物的一個(gè)統(tǒng)稱,是抽象的,特征 被稱為 屬性,行為 被稱為 方法。
對象 是 由類創(chuàng)建出來的一個(gè)具體存在,是類的實(shí)例化。
在程序開發(fā)中,要設(shè)計(jì)一個(gè)類,通常需要滿足一下三個(gè)要素: 類名 這類事物的名字,滿足大駝峰命名法 屬性 這類事物具有什么樣的特征 方法 這類事物具有什么樣的行為
2. 面向?qū)ο蠡A(chǔ)語法
2.1 dir 內(nèi)置函數(shù)和內(nèi)置方法
在 Python 中 對象幾乎是無所不在的,我們之前學(xué)習(xí)的 變量、數(shù)據(jù)、函數(shù) 都是對象。在 Python 中可以使用以下兩個(gè)方法驗(yàn)證:
在 標(biāo)識符 / 數(shù)據(jù) 后輸入一個(gè)點(diǎn) .,然后按下 TAB 鍵,iPython 會提示該對象能夠調(diào)用的方法列表。
使用內(nèi)置函數(shù) dir 傳入 標(biāo)識符 / 數(shù)據(jù),可以查看對象內(nèi)的 所有屬性及方法。
提示__方法名__格式的方法是 Python 提供的 內(nèi)置方法 / 屬性。
序號 方法名 類型 作用 01 __new__ 方法 創(chuàng)建對象時(shí),會被 自動(dòng) 調(diào)用 02 __init__ 方法 對象被初始化時(shí),會被 自動(dòng) 調(diào)用 03 __del__ 方法 對象被從內(nèi)存中銷毀前,會被 自動(dòng) 調(diào)用 04 __str__ 方法 返回對象的描述信息,print 函數(shù)輸出使用
提示 利用好 dir() 函數(shù),在學(xué)習(xí)時(shí)很多內(nèi)容就不需要死記硬背了。
2.2 定義簡單的類(只包含方法)
面向?qū)ο笫歉蟮姆庋b,在 一個(gè)類中封裝多個(gè)方法,這樣通過這個(gè)類創(chuàng)建出來的對象,就可以直接調(diào)用這些方法了!
定義一個(gè)只包含方法的類:
class 類名:
def 方法1(self, 參數(shù)列表):
pass
def 方法2(self, 參數(shù)列表):
pass
方法 的定義格式和之前學(xué)習(xí)過的函數(shù)幾乎一樣,區(qū)別在于第一個(gè)參數(shù)必須是 self。注意:類名的 命名規(guī)則 要符合 大駝峰命名法。當(dāng)一個(gè)類定義完成之后,要使用這個(gè)類來創(chuàng)建對象,語法格式如下:
對象變量 = 類名()
在面向?qū)ο箝_發(fā)中,引用的概念是同樣適用的!
使用 print輸出 對象變量,默認(rèn)情況下,是能夠輸出這個(gè)變量 引用的對象 是 由哪一個(gè)類創(chuàng)建的對象,以及 在內(nèi)存中的地址(十六進(jìn)制表示)。
提示:在計(jì)算機(jī)中,通常使用 十六進(jìn)制 表示 內(nèi)存地址。
如果在開發(fā)中,希望使用 print輸出 對象變量 時(shí),能夠打印 自定義的內(nèi)容,就可以利用 __str__這個(gè)內(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__方法必須返回一個(gè)字符串。
2.3 方法中的 self 參數(shù)
在 Python 中,要 給對象設(shè)置屬性,非常的容易,只需要在 類的外部的代碼 中直接通過 對象.設(shè)置一個(gè)屬性即可,但是不推薦使用:
class Cat:
"""這是一個(gè)貓類"""
def eat(self):
print("小貓愛吃魚")
def drink(self):
print("小貓?jiān)诤人?)
tom = Cat()
# 給對象設(shè)置屬性
tom.name = "Tom"
因?yàn)椋?span style="-webkit-tap-highlight-color: transparent;box-sizing: border-box;font-weight: 700;">對象屬性的封裝應(yīng)該封裝在類的內(nèi)部
由哪一個(gè)對象調(diào)用的方法,方法內(nèi)的 self就是哪一個(gè)對象的引用
在類封裝的方法內(nèi)部,self 就表示當(dāng)前調(diào)用方法的對象自己,在方法內(nèi)部:
可以通過 self.訪問對象的屬性,也可以通過 self.調(diào)用對象的其他方法。調(diào)用方法時(shí),程序員不需要傳遞 self 參數(shù)。
在 類的外部,通過變量名.訪問對象的 屬性和方法
在 類封裝的方法中,通過 self.訪問對象的 屬性和方法
2.4 初始化方法:__init__
當(dāng)使用 類名() 創(chuàng)建對象時(shí),會 自動(dòng) 執(zhí)行以下操作:
為對象在內(nèi)存中分配空間 —— 創(chuàng)建對象
為對象的屬性設(shè)置初始值 —— 初始化方法(__init__)
__init__ 方法是 專門 用來定義一個(gè)類具有哪些屬性的方法!
在 __init__ 方法內(nèi)部使用 self.屬性名 = 屬性的初始值 就可以定義屬性,定義屬性之后,再使用 類創(chuàng)建的對象,都會擁有該屬性。
在開發(fā)中,如果希望在 創(chuàng)建對象的同時(shí),就設(shè)置對象的屬性,可以對 __init__ 方法進(jìn)行 改造:把希望設(shè)置的屬性值,定義成 __init__方法的參數(shù) 在方法內(nèi)部使用 self.屬性 = 形參 接收外部傳遞的參數(shù) 在創(chuàng)建對象時(shí),使用 類名(屬性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)用場景
在實(shí)際開發(fā)中,對象 的 某些屬性或方法 可能只希望 在對象的內(nèi)部被使用,而 不希望在外部被訪問到
私有屬性 就是 對象 不希望公開的 屬性
私有方法 就是 對象 不希望公開的 方法
定義方式
在 定義屬性或方法時(shí),在 屬性名或者方法名前 增加 兩個(gè)下劃線,定義的就是 私有屬性或方法:
私有屬性和私有方法
偽私有屬性和私有方法Python 中,并沒有 真正意義 的 私有在給 屬性、方法 命名時(shí),實(shí)際是對名稱做了一些特殊處理,使得外界無法訪問到處理方式:在 名稱 前面加上_類名 => _類名__名稱
# 私有屬性,外部不能直接訪問到
print(xiaofang._Women__age)
# 私有方法,外部不能直接調(diào)用
xiaofang._Women__secret()
提示:在日常開發(fā)中,不要使用這種方式,訪問對象的 私有屬性 或 私有方法。
3. 封裝、繼承和多態(tài)
面向?qū)ο笕筇匦裕?/p>
封裝 根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個(gè)抽象的 類 中
繼承 實(shí)現(xiàn)代碼的重用,相同的代碼不需要重復(fù)的編寫
多態(tài) 不同的對象調(diào)用相同的方法,產(chǎn)生不同的執(zhí)行結(jié)果,增加代碼的靈活度
3.1 繼承
3.1.1 單繼承
繼承的概念:子類 擁有 父類 以及 父類的父類 中封裝的所有 屬性 和 方法。
class 類名(父類名):
pass
當(dāng) 父類 的方法實(shí)現(xiàn)不能滿足子類需求時(shí),可以對方法進(jìn)行重寫(override)重寫 父類方法有兩種情況:
覆蓋 父類的方法:父類的方法實(shí)現(xiàn) 和 子類的方法實(shí)現(xiàn)完全不同
具體的實(shí)現(xiàn)方式,就相當(dāng)于在 子類中 定義了一個(gè) 和父類同名的方法并且實(shí)現(xiàn)。對父類方法進(jìn)行 擴(kuò)展:子類的方法實(shí)現(xiàn) 中 包含 父類的方法實(shí)現(xiàn)
在子類中 重寫 父類的方法;在需要的位置使用 super().父類方法 來調(diào)用父類方法的執(zhí)行代碼;其他的位置針對子類的需求,編寫 子類特有的代碼實(shí)現(xiàn)。
關(guān)于 super
在 Python 中 super 是一個(gè) 特殊的類
super()就是使用 super 類創(chuàng)建出來的對象
最常 使用的場景就是在 重寫父類方法時(shí),調(diào)用 在父類中封裝的方法實(shí)現(xiàn)
調(diào)用父類方法的另外一種方式:在 Python 2.x 時(shí),如果需要調(diào)用父類的方法,還可以使用以下方式:父類名.方法(self)。目前在 Python 3.x 還支持這種方式,但不推薦使用,因?yàn)橐坏?父類發(fā)生變化,方法調(diào)用位置的 類名 同樣需要修改。
父類的 私有屬性 和 私有方法
子類對象 不能 在自己的方法內(nèi)部,直接 訪問 父類的 私有屬性 或 私有方法子類對象 可以通過 父類 的 公有方法 間接 訪問到 私有屬性 或 私有方法
私有屬性、方法 是對象的隱私,不對外公開,外界 以及 子類 都不能直接訪問 私有屬性、方法 通常用于做一些內(nèi)部的事情
3.1.2 多繼承
子類 可以擁有 多個(gè)父類,并且具有 所有父類 的 屬性 和 方法,例如:孩子 會繼承自己 父親 和 母親 的 特性。
class 子類名(父類名1, 父類名2...):
pass
Python 中的 MRO算法(Method Resolution Order)
如果 不同的父類 中存在 同名的方法,子類對象 在調(diào)用方法時(shí),會調(diào)用 哪一個(gè)父類中的方法呢?
提示:開發(fā)時(shí),應(yīng)該盡量避免這種容易產(chǎn)生混淆的情況!—— 如果 父類之間 存在 同名的屬性或者方法,應(yīng)該 盡量避免使用多繼承。Python 中針對 類 提供了一個(gè) 內(nèi)置屬性__mro__ 可以查看 方法 搜索順序 在搜索方法時(shí),是按照 mro 的輸出結(jié)果 從左至右 的順序查找的 如果在當(dāng)前類中 找到方法,就直接執(zhí)行,不再搜索 如果 沒有找到,就查找下一個(gè)類 中是否有對應(yīng)的方法,如果找到,就直接執(zhí)行,不再搜索 如果找到最后一個(gè)類,還沒有找到方法,程序報(bào)錯(cuò)
MRO 是 method resolution order —— 方法搜索順序,主要用于 在多繼承時(shí)判斷 方法、屬性 的調(diào)用 路徑
新式類與舊式(經(jīng)典)類
新式類:以 object 為基類的類,推薦使用
經(jīng)典類:不以 object為基類的類,不推薦使用
在 Python 3.x 中定義類時(shí),如果沒有指定父類,會 默認(rèn)使用 object作為該類的 基類 —— Python 3.x 中定義的類都是 新式類,在 Python 2.x 中定義類時(shí),如果沒有指定父類,則不會以 object 作為 基類。
為了保證編寫的代碼能夠同時(shí)在 Python 2.x 和 Python 3.x 運(yùn)行!今后在定義類時(shí),如果沒有父類,建議統(tǒng)一繼承自 object:
class 類名(object):
pass
object 是 Python 為所有對象提供的 基類,提供有一些內(nèi)置的屬性和方法,可以使用 dir(object) 函數(shù)查看。
3.2 多態(tài)
面向?qū)ο笕筇匦裕?/p>
封裝 根據(jù) 職責(zé) 將 屬性 和 方法 封裝 到一個(gè)抽象的 類 中 定義類的準(zhǔn)則
繼承 實(shí)現(xiàn)代碼的重用,相同的代碼不需要重復(fù)的編寫 設(shè)計(jì)類的技巧 子類針對自己特有的需求,編寫特定的代碼
多態(tài) 不同的 子類對象 調(diào)用相同的 父類方法,產(chǎn)生不同的執(zhí)行結(jié)果 增加代碼的靈活度 以 繼承 和 重寫父類方法 為前提 調(diào)用方法的技巧,不會影響到類的內(nèi)部設(shè)計(jì)
多態(tài) 更容易編寫出出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化!
案例:在 Dog 類中封裝方法 game:普通狗只是簡單的玩耍定義 XiaoTianDog 繼承自 Dog,并且重寫 game 方法:哮天犬需要在天上玩耍定義 Person 類,并且封裝一個(gè) 和狗玩 的方法:在方法內(nèi)部,直接讓 狗對象 調(diào)用 game 方法
多態(tài)示例
Person 類中只需要讓 狗對象 調(diào)用 game 方法,而不關(guān)心具體是 什么狗。
4. 類屬性和類方法
4.1 類的結(jié)構(gòu)
通常會把:創(chuàng)建出來的 對象 叫做 類的實(shí)例創(chuàng)建對象的 動(dòng)作 叫做 實(shí)例化對象的屬性 叫做 實(shí)例屬性對象調(diào)用的方法 叫做 實(shí)例方法每一個(gè)對象 都有自己獨(dú)立的內(nèi)存空間,保存各自不同的屬性多個(gè)對象的方法,在內(nèi)存中只有一份,在調(diào)用方法時(shí),需要把對象的引用傳遞到方法內(nèi)部
各個(gè)不同的屬性,獨(dú)一份的方法
在 Python 中,類是一個(gè)特殊的對象。
Python 中 一切皆對象:
class AAA: 定義的類屬于 類對象 obj1 = AAA() 屬于 實(shí)例對象
在程序運(yùn)行時(shí),類同樣會被加載到內(nèi)存在程序運(yùn)行時(shí),類對象在內(nèi)存中只有一份,使用 一個(gè)類可以創(chuàng)建出很多個(gè)對象實(shí)例除了封裝實(shí)例的屬性和方法外,類對象還可以擁有自己的屬性和方法——類屬性、類方法,通過 類名. 的方式可以 訪問類的屬性 或者 調(diào)用類的方法
類的結(jié)構(gòu)
4.2 類屬性和實(shí)例屬性
類屬性 就是 類對象中定義的屬性通常用來記錄與這個(gè)類相關(guān)的特征類屬性不會用于記錄具體對象的特征示例:定義一個(gè) 工具類,每件工具都有自己的 name:需求 —— 知道使用這個(gè)類,創(chuàng)建了多少個(gè)工具對象?
屬性的獲取機(jī)制
在 Python 中 屬性的獲取 存在一個(gè) 向上查找機(jī)制
因此,要訪問類屬性有兩種方式:
類名.類屬性
對象.類屬性 (不推薦,因?yàn)槿绻褂?對象.類屬性 = 值 賦值語句,只會給對象添加一個(gè)屬性,而不會影響到類屬性的值)
4.3 類方法和靜態(tài)方法
4.3.1 類方法
類屬性 就是針對 類對象 定義的屬性 使用 賦值語句 在 class 關(guān)鍵字下方可以定義 類屬性 類屬性 用于記錄 與這個(gè)類相關(guān) 的特征
類方法 就是針對 類對象 定義的方法 在 類方法 內(nèi)部可以直接訪問 類屬性 或者調(diào)用其他的 類方法
語法如下
@classmethod
def 類方法名(cls):
pass
類方法需要用 修飾器 @classmethod 來標(biāo)識,告訴解釋器這是一個(gè)類方法
類方法的 第一個(gè)參數(shù) 應(yīng)該是 cls 由 哪一個(gè)類 調(diào)用的方法,方法內(nèi)的 cls 就是 哪一個(gè)類的引用 這個(gè)參數(shù)和 實(shí)例方法 的第一個(gè)參數(shù)是 self 類似 提示 使用其他名稱也可以,不過習(xí)慣使用 cls
通過 類名. 調(diào)用 類方法,調(diào)用方法時(shí),不需要傳遞 cls 參數(shù)
在方法內(nèi)部 可以通過 cls. 訪問類的屬性 也可以通過 cls. 調(diào)用其他的類方法
示例
定義一個(gè) 工具類,每件工具都有自己的 name
需求 —— 在 類 封裝一個(gè) show_tool_count 的類方法,輸出使用當(dāng)前這個(gè)類,創(chuàng)建的對象個(gè)數(shù)
@classmethod
def show_tool_count(cls):
"""顯示工具對象的總數(shù)"""
print("工具對象的總數(shù) %d" % cls.count)
4.3.2 靜態(tài)方法
在開發(fā)時(shí),如果需要在 類 中封裝一個(gè)方法,這個(gè)方法:既 不需要 訪問 實(shí)例屬性 或者調(diào)用 實(shí)例方法 也 不需要 訪問 類屬性 或者調(diào)用 類方法
這個(gè)時(shí)候,可以把這個(gè)方法封裝成一個(gè) 靜態(tài)方法
語法如下
@staticmethod
def 靜態(tài)方法名():
pass
靜態(tài)方法 需要用 修飾器 @staticmethod 來標(biāo)識,告訴解釋器這是一個(gè)靜態(tài)方法
通過 類名. 調(diào)用 靜態(tài)方法
示例:
靜態(tài)方法 show_help 顯示游戲幫助信息
類方法 show_top_score 顯示歷史最高分
實(shí)例方法 start_game 開始當(dāng)前玩家的游戲
探索:
實(shí)例方法 —— 方法內(nèi)部需要訪問 實(shí)例屬性 實(shí)例方法 內(nèi)部可以使用 類名. 訪問類屬性
類方法 —— 方法內(nèi)部 只需要訪問 類屬性
靜態(tài)方法 —— 方法內(nèi)部,不需要訪問 實(shí)例屬性 和 類屬性
5. 單例
5.1 單例設(shè)計(jì)模式
設(shè)計(jì)模式 設(shè)計(jì)模式 是 前人工作的總結(jié)和提煉,通常,被人們廣泛流傳的設(shè)計(jì)模式都是針對 某一特定問題 的成熟的解決方案 使用 設(shè)計(jì)模式 是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
單例設(shè)計(jì)模式 目的 —— 讓 類 創(chuàng)建的對象,在系統(tǒng)中 只有 唯一的一個(gè)實(shí)例 每一次執(zhí)行 類名() 返回的對象,內(nèi)存地址是相同的
單例設(shè)計(jì)模式的應(yīng)用場景 音樂播放 對象 回收站 對象 打印機(jī) 對象 ……
5.2 靜態(tài)方法:__new__
使用 類名() 創(chuàng)建對象時(shí),Python 的解釋器 首先 會 調(diào)用 __new__ 方法為對象 分配空間
__new__ 是一個(gè) 由 object 基類提供的 內(nèi)置的靜態(tài)方法,主要作用有兩個(gè):在內(nèi)存中為對象 分配空間 返回 對象的引用
Python 的解釋器獲得對象的 引用 后,將引用作為 第一個(gè)參數(shù),傳遞給 __init__ 方法
重寫 __new__ 方法 的代碼非常固定!
重寫 __new__ 方法 一定要 return super().__new__(cls),否則 Python 的解釋器 得不到分配了空間的 對象引用,就不會調(diào)用對象的初始化方法
注意:__new__ 是一個(gè)靜態(tài)方法,在調(diào)用時(shí)需要 主動(dòng)傳遞 cls 參數(shù)
5.3 Python 中的單例
單例 —— 讓 類 創(chuàng)建的對象,在系統(tǒng)中 只有 唯一的一個(gè)實(shí)例 定義一個(gè) 類屬性,初始值是 None,用于記錄 單例對象的引用 重寫 __new__ 方法 如果 類屬性 is None,調(diào)用父類方法分配空間,并在類屬性中記錄結(jié)果 返回 類屬性 中記錄的 對象引用
只執(zhí)行一次初始化工作
在每次使用 類名() 創(chuàng)建對象時(shí),Python 的解釋器都會自動(dòng)調(diào)用兩個(gè)方法:__new__ 分配空間 __init__ 對象初始化
在對 __new__ 方法改造之后,每次都會得到 第一次被創(chuàng)建對象的引用
但是:初始化方法還會被再次調(diào)用
需求
讓 初始化動(dòng)作 只被 執(zhí)行一次
解決辦法
定義一個(gè)類屬性 init_flag 標(biāo)記是否 執(zhí)行過初始化動(dòng)作,初始值為 False
在 __init__ 方法中,判斷 init_flag,如果為 False 就執(zhí)行初始化動(dòng)作
然后將 init_flag 設(shè)置為 True
這樣,再次 自動(dòng) 調(diào)用 __init__ 方法時(shí),初始化動(dòng)作就不會被再次執(zhí)行 了
Tips
1、Python 能夠自動(dòng)的將一對括號內(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)建異常對象 - 使用異常的錯(cuò)誤信息字符串作為參數(shù)
ex = Exception("密碼長度不夠")
# 2> 拋出異常對象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print("發(fā)現(xiàn)錯(cuò)誤:%s" % result)
2、一個(gè)對象的 屬性 可以是 另外一個(gè)類創(chuàng)建的對象。3、在__init__方法中定義類的屬性時(shí),如果 不知道設(shè)置什么初始值,可以設(shè)置為 None):None 關(guān)鍵字 表示 什么都沒有,表示一個(gè) 空對象,沒有方法和屬性,是一個(gè)特殊的常量??梢詫?None 賦值給任何一個(gè)變量。
在 Python 中針對 None 比較時(shí),建議使用is 判斷
4、eval() 函數(shù)十分強(qiáng)大 —— 將字符串 當(dāng)成 有效的表達(dá)式 來求值 并 返回計(jì)算結(jié)果
在開發(fā)時(shí)千萬不要使用 eval 直接轉(zhuǎn)換 input 的結(jié)果,舉個(gè)例子:
__import__('os').system('ls')# 等價(jià)代碼import osos.system("終端命令")
-END-
推薦閱讀
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!






