文章目錄
- 1 環境安裝
- 2 Python的第一程式Hello World
- 3 變數定義和型別
- 3.1 什么是變數,
- 3.2 變數的型別
- 3.3 變數的命名規則
- 3.4 常用的資料型別轉換
- 4 注釋
- 4.1 單行注釋
- 4.2 多行注釋
- 4.3 編碼
- 5 輸入輸出
- 5.1 輸入
- 5.2 輸出
- 5.2.1 格式化輸出
- 6 運算子
- 7 判斷陳述句
- 7.1 if陳述句
- 7.2 if-else陳述句
- 7.3 elif
- 7.4 if嵌套
- 8 回圈、break和continue
- 8.1 while回圈
- 8.2 while回圈嵌套
- 8.3 for回圈
- 8.5 break
- 8.6 continue
- 9 字串、串列、元組、字典
- 9.1 字串
- 9.2 字串常見操作
- 9.2.1 find
- 9.2.2 index
- 9.2.3 count
- 9.2.4 replace
- 9.2.5 split
- 9.2.6 capitalize
- 9.2.7 title
- 9.2.8 startswith
- 9.2.9 endswith
- 9.2.10 lower
- 9.2.11 upper
- 9.2.12 ljust
- 9.2.13 rjust
- 9.2.14 center
- 9.2.15 lstrip
- 9.2.16 rstrip
- 9.2.17 strip
- 9.2.18 rfind
- 9.2.19 rindex
- 9.2.20 partition
- 9.2.21 rpartition
- 9.2.22 splitlines
- 9.2.23 isalpha
- 9.2.24 isdigit
- 9.2.25 isalnum
- 9.2.26 isspace
- 9.2.27 join
- 9.3 串列List
- 9.3.1 for回圈遍歷list
- 9.3.2 while回圈遍歷list
- 9.4 串列的常用操作
- 9.4.1 添加元素("增"append, extend, insert)
- 9.4.2修改元素("改")
- 9.4.3 查找元素("查"in, not in, index, count)
- 9.4.4 洗掉元素("刪"del, pop, remove)
- 9.4.5 排序(sort, reverse)
- 9.4.6 串列的嵌套
- 9.5 元組
- 9.5.1 訪問元組
- 9.5.2 修改元組
- 9.5.3 元組的內置函式count, index
- 9.6 字典
- 9.6.1 根據鍵訪問值
- 9.7 字典的常用操作
- 9.7.1 修改元素
- 9.7.2 添加元素
- 9.7.3 洗掉元素
- 9.7.4 字典的長度
- 9.7.5 找出字典中的所有key
- 9.7.6 找出字典所有的value
- 9.7.7 找出字典的(鍵,值)
- 9.7.8 判斷key是否存在
- 9.7.9 遍歷字典的幾種方式
- 10 函式
- 10.1 定義函式
- 10.2 呼叫函式
- 10.3 函式的注釋
- 10.4 函式的引數
- 10.4.1 引數的定義
- 10.4.2 引數的分類
- 10.4.3 引數的傳遞
- 10.5 函式的回傳值
- 10.6 區域變數與全域變數
- 10.7 遞回函式
- 10.8 匿名函式
- 10.8.1 定義
- 10.8.2 應用場合
- 11 檔案操作
- 11.1 打開與關閉
- 11.1.1 打開檔案
- 11.1.2 關閉檔案
- 11.2 檔案的讀寫
- 11.2.1 寫資料(write)
- 11.2.2 讀資料(read)
- 11.2.3 讀資料(readlines)
- 11.2.4 讀資料(readline)
- 11.3 檔案的常用操作
- 11.3.1 獲取當前讀寫的位置
- 11.3.2 定位到某個位置
- 11.3.3 檔案重命名
- 11.3.4 洗掉檔案
- 11.4 檔案夾的相關操作
- 11.4.1 創建檔案夾
- 11.4.2 獲取當前目錄
- 11.4.3 改變默認目錄
- 11.4.4 獲取目錄串列
- 11.4.5 洗掉檔案夾
- 11.4.6 檢測檔案夾是否存在
- 11.4.7 創建多級檔案夾
- 12 面向物件編程
- 12.1 類和物件
- 12.1.1 類
- 12.2.2 物件
- 12.2.3 類和物件的關系
- 12.2.4 定義類
- 12.2.5 創建物件
- 12.2.6 `__init__()`方法
- 12.2.7 魔法方法
- 12.2.8 self
- 12.2 屬性
- 12.2.1 類屬性
- 12.2.2 實體屬性(物件屬性)
- 12.2.3 私有屬性
- 12.3 繼承
- 12.3.1 私有屬性和方法的繼承
- 12.3.2 多繼承
- 12.3.3 重寫父類方法
- 12.3.4 呼叫父類的方法
- 12.4 多型
- 12.5 靜態方法和類方法
- 12.5.1 類方法
- 12.5.2 靜態方法
- 13 例外
- 13.1 捕獲例外
- 13.1.1 捕獲例外 try...except...
- 13.1.2 except捕獲多個例外
- 13.1.3 獲取例外的資訊描述
- 13.1.4捕獲所有例外
- 13.1.5 else
- 13.1.6 try...finally...
- 13.2 例外的傳遞
- 13.2.1. try嵌套中
- 13.2.2 函式嵌套呼叫中
- 13.3 拋出自定義的例外
- 13.4 例外處理中拋出例外
- 14 模塊
- 14.1 模塊介紹
- 14.1.1 Python中的模塊
- 14.1.2 import
- 14.1.3 from…import
- 14.1.4 from … import *
- 14.1.5 as
- 14.1.6 定位模塊
- 14.2 制作模塊
- 14.2.1 定義自己的模塊
- 14.2.2 呼叫自己定義的模塊
- 14.2.3 測驗模塊
- 14.3 模塊中的`__all__`
- 14.3.1 沒有`__all__`
- 14.3.2. 模塊中有`__all__`
- 14.4 python中的包
- 14.4.1. 引入包
- 14.4.2 `__init__.py`檔案作用
- 14.5 模塊發布
- 14.6 模塊安裝、使用
- 14.6.1 安裝的方式
- 14.6.2 模塊的引入
- 14.2.3 測驗模塊
- 14.3 模塊中的`__all__`
- 14.3.1 沒有`__all__`
- 14.3.2. 模塊中有`__all__`
- 14.4 python中的包
- 14.4.1. 引入包
- 14.4.2 `__init__.py`檔案作用
- 14.5 模塊發布
- 14.6 模塊安裝、使用
- 14.6.1 安裝的方式
- 14.6.2 模塊的引入
1 環境安裝
學習python開發,首先要學會安裝Python環境,我一般使用Anaconda+Pycharm作為開發環境,Anaconda是一個開源的Python發行版本,其包含了conda、Python等180多個科學包及其依賴項,因為包含了大量的科學包,Anaconda 的下載檔案比較大(約 531 MB),如果覺得安裝包太大可以使用Miniconda,
關于環境的安裝我已經寫了多篇文章,比如:
Ubuntu20.04的開發環境搭建:(4條訊息) Ubuntu 20.04安裝 Anaconda和Pycharm_AI浩-CSDN博客
Win10的開發環境搭建:(4條訊息) Win10 安裝Anaconda、Pycharm、Tensorflow和Pytorch_AI浩-CSDN博客
Anaconda的歷史版本下載:(4條訊息) Anaconda歷史版本_AI浩-CSDN博客,如果不想使用最新的版本,可以找到以前的版本,
2 Python的第一程式Hello World
新建個工程,將其命名為“Python基礎”,然后點擊“Create”

然后,右擊工程,選擇“New”,然后選擇“Python File”,

將其命名為“第一個Python程式”,然后按“Enter”鍵

到這里我們創建Python檔案的作業就完成成了,下面試試Hello World,
將下面的代碼,復制進去:
print('hello world')
然后右鍵選擇Run,或者使用快捷鍵“Ctrl+Shift+F10",

運行結果:

喜歡敲命令的朋友可以選擇命令列運行:
python 第一個Python程式.py

3 變數定義和型別
3.1 什么是變數,
打個比方:我最近買了兩本書,一本售價89,一本售價118,我想用python計算一下兩本書一共要多少錢:
num1 = 89
num2 = 118
num3 = num1 + num2
print(num3)
運行結果:207
所謂的變數就是對計算機存盤值的表示,從上面的例子,我們可以得出:
Python 中的變數不需要宣告,每個變數在使用前都必須賦值,變數賦值以后該變數才會被創建,
在 Python 中,變數沒有型別,我們所說的"型別"是變數所指的記憶體中物件的型別,
等號(=)用來給變數賦值,
等號(=)運算子左邊是一個變數名,等號(=)運算子右邊是存盤在變數中的值,
3.2 變數的型別

如何知道一個變數的型別呢?
在python中,只要定義了一個變數,而且它有資料,那么它的型別就已經確定了,不需要咱們開發者主動的去說明它的型別,系統會自動辨別
可以使用type(變數的名字),來查看變數的型別,例如:
num1 = 89
num2 = 118
num3 = num1 + num2
print(type(num3))
運行結果:<class ‘int’>
3.3 變數的命名規則
變數的命名規則:
-
由字母、下劃線和數字組成,且數字不能開頭,
-
不能使用python的關鍵字,
? 關鍵字有:
and as assert break class continue def del
elif else except exec finally for from global
if in import is lambda not or pass
print raise return try while with yield
-
起一個有意義的名字,盡量做到看一眼就知道是什么意思(提高代碼可 讀性) 比如: 名字 就定義為 name ,年齡用age,
-
駝峰命名法
第一種 小駝峰式命名法(lower camel case): 第一個單詞以小寫字母開始;第二個單詞的首字母大寫,例如:myName、aDog
第二種 大駝峰式命名法(upper camel case): 每一個單字的首字母都采用大寫字母,例如:FirstName、LastName
不過在程式員中還有一種命名法比較流行,就是用下劃線“_”來連接所有的單詞,比如send_buf
注:python中的識別符號是區分大小寫的

3.4 常用的資料型別轉換
| 函式 | 說明 |
|---|---|
| int(x [,base ]) | 將x轉換為一個整數 |
| long(x [,base ]) | 將x轉換為一個長整數 |
| float(x ) | 將x轉換到一個浮點數 |
| complex(real [,imag ]) | 創建一個復數 |
| str(x ) | 將物件 x 轉換為字串 |
| repr(x ) | 將物件 x 轉換為運算式字串 |
| eval(str ) | 用來計算在字串中的有效Python運算式,并回傳一個物件 |
| tuple(s ) | 將序列 s 轉換為一個元組 |
| list(s ) | 將序列 s 轉換為一個串列 |
| chr(x ) | 將一個整數轉換為一個字符 |
| unichr(x ) | 將一個整數轉換為Unicode字符 |
| ord(x ) | 將一個字符轉換為它的整數值 |
| hex(x ) | 將一個整數轉換為一個十六進制字串 |
| oct(x ) | 將一個整數轉換為一個八進制字串 |
舉例
a = '100' # 此時a的型別是一個字串,里面存放了100這3個字符
b = int(a) # 此時b的型別是整型,里面存放的是數字100
print("a=%d"%b)
4 注釋
4.1 單行注釋
以#開頭,#右邊的所有東西當做說明,而不是真正要執行的程式,起輔助說明作用
# 我是注釋,可以在里寫一些功能說明之類的哦
print('hello world')
4.2 多行注釋
'''我是多行注釋,可以寫很多很多行的
哈哈哈,,,
哈哈哈,,,
'''
'''
我是多行注釋,可以寫很多很多行的
哈哈哈,,,
哈哈哈,,,
'''
print('hello world')
4.3 編碼
如果直接在程式中用到了中文,比如
print('你好,我是AI浩')
如果直接運行輸出,程式會出現編碼的問題(這和平臺有關)
解決的辦法為:在程式的開頭寫入如下代碼,這就是中文注釋
#coding=utf-8
修改之后的程式:
#coding=utf-8
print('你好,我是AI浩')
運行結果:
你好
注意:在python的語法規范中推薦使用的方式:
# -*- coding:utf-8 -*-
5 輸入輸出
5.1 輸入
input()接受運算式輸入,并把運算式的結果賦值給等號左邊的變數
a = input("請輸入數字:")
print(a)
print(type(a))
b=input("請輸入字串:")
print(b)
print(type(b))
c= input("請輸入數學運算式:")
print(c)
print(type(c))
d= input("請輸入字串運算式:")
print(d)
print(type(d))
運行結果:
請輸入數字:123
123
<class 'str'>
請輸入字串:abc
abc
<class 'str'>
請輸入數學運算式:123+456
123+456
<class 'str'>
請輸入字串運算式:sdsf,1223
sdsf,1223
<class 'str'>
5.2 輸出
print() 將python的輸入
# 列印提示
print('hello world')
5.2.1 格式化輸出
如下代碼:
age = 100
print("我今年%d歲"%age)
age += 1
print("我今年%d歲"%age)
age += 1
print("我今年%d歲"%age)
運行結果:
我今年100歲
我今年101歲
我今年102歲
在程式中,看到了%這樣的運算子,這就是Python中格式化輸出,
age = 18
name = "lifeifei"
print("我的姓名是%s,年齡是%d"%(name,age))
常用的格式符號
| 格式符號 | 轉換 |
|---|---|
| %c | 字符 |
| %s | 通過str() 字串轉換來格式化 |
| %i | 有符號十進制整數 |
| %d | 有符號十進制整數 |
| %u | 無符號十進制整數 |
| %o | 八進制整數 |
| %x | 十六進制整數(小寫字母) |
| %X | 十六進制整數(大寫字母) |
| %e | 索引符號(小寫’e’) |
| %E | 索引符號(大寫“E”) |
| %f | 浮點實數 |
| %g | %f和%e 的簡寫 |
| %G | %f和%E的簡寫 |
換行輸出
在輸出的時候,如果有\n那么,此時\n后的內容會在另外一行顯示
print("1234567890-------") # 會在一行顯示
print("1234567890\n-------") # 一行顯示1234567890,另外一行顯示-------
運行結果:
1234567890-------
1234567890
-------
6 運算子
python支持以下幾種運算子
- 算術運算子
下面以a=10 ,b=20為例進行計算
| 運算子 | 描述 | 實體 |
|---|---|---|
| + | 加 | 兩個物件相加 a + b 輸出結果 30 |
| - | 減 | 得到負數或是一個數減去另一個數 a - b 輸出結果 -10 |
| * | 乘 | 兩個數相乘或是回傳一個被重復若干次的字串 a * b 輸出結果 200 |
| / | 除 | x除以y b / a 輸出結果 2 |
| // | 取整除 | 回傳商的整數部分 9//2 輸出結果 4 , 9.0//2.0 輸出結果 4.0 |
| % | 取余 | 回傳除法的余數 b % a 輸出結果 0 |
| ** | 冪 | 回傳x的y次冪 a**b 為10的20次方, 輸出結果 100000000000000000000 |
>>> 9/2.0
4.5
>>> 9//2.0
4.0
- 賦值運算子
| 運算子 | 描述 | 實體 |
|---|---|---|
| = | 賦值運算子 | 把=號右邊的結果給左邊的變數 num=1+2*3 結果num的值為7 |
>>> a, b = 1, 2
>>> a
1
>>> b
2
- 復合賦值運算子
| 運算子 | 描述 | 實體 |
|---|---|---|
| += | 加法賦值運算子 | c += a 等效于 c = c + a |
| -= | 減法賦值運算子 | c -= a 等效于 c = c - a |
| *= | 乘法賦值運算子 | c *= a 等效于 c = c * a |
| /= | 除法賦值運算子 | c /= a 等效于 c = c / a |
| %= | 取模賦值運算子 | c %= a 等效于 c = c % a |
| **= | 冪賦值運算子 | c **= a 等效于 c = c ** a |
| //= | 取整除賦值運算子 | c //= a 等效于 c = c // a |
- 比較(即關系)運算子
python中的比較運算子如下表
| 運算子 | 描述 | 示例 |
|---|---|---|
| == | 檢查兩個運算元的值是否相等,如果是則條件變為真, | 如a=3,b=3則(a == b) 為 true. |
| != | 檢查兩個運算元的值是否相等,如果值不相等,則條件變為真, | 如a=1,b=3則(a != b) 為 true. |
| <> | 檢查兩個運算元的值是否相等,如果值不相等,則條件變為真, | 如a=1,b=3則(a <> b) 為 true,這個類似于 != 運算子 |
| > | 檢查左運算元的值是否大于右運算元的值,如果是,則條件成立, | 如a=7,b=3則(a > b) 為 true. |
| < | 檢查左運算元的值是否小于右運算元的值,如果是,則條件成立, | 如a=7,b=3則(a < b) 為 false. |
| >= | 檢查左運算元的值是否大于或等于右運算元的值,如果是,則條件成立, | 如a=3,b=3則(a >= b) 為 true. |
| <= | 檢查左運算元的值是否小于或等于右運算元的值,如果是,則條件成立, | 如a=3,b=3則(a <= b) 為 true. |
- 邏輯運算子
| 運算子 | 邏輯運算式 | 描述 | 實體 |
|---|---|---|---|
| and | x and y | 布爾"與" - 如果 x 為 False,x and y 回傳 False,否則它回傳 y 的計算值, | (a and b) 回傳 20, |
| or | x or y | 布爾"或" - 如果 x 是 True,它回傳 True,否則它回傳 y 的計算值, | (a or b) 回傳 10, |
| not | not x | 布爾"非" - 如果 x 為 True,回傳 False ,如果 x 為 False,它回傳 True, | not(a and b) 回傳 False |
7 判斷陳述句
7.1 if陳述句
- if陳述句是用來進行判斷的,其使用格式如下:
if 要判斷的條件:
條件成立時,要做的事情
例1:
age = 30
print("------if判斷開始------")
if age >= 18:
print ("我已經成年了,我可以約妹子了!!!")
print ("------if判斷結束------")
運行結果:
------if判斷開始------
我已經成年了,我可以約妹子了!!!
------if判斷結束------
例2:
age = 16
print("------if判斷開始------")
if age >= 18:
print ("我已經成年了,我可以約妹子了!!!")
print ("------if判斷結束------")
運行結果:
------if判斷開始------
------if判斷結束------
**總結:**以上2個例子僅僅是age變數的值不一樣,結果卻不同;能夠看得出if判斷陳述句的作用:就是當滿足一定條件時才會執行那塊代碼,否則就不執行那塊代碼
7.2 if-else陳述句
if 條件:
滿足條件時要做的事情1
滿足條件時要做的事情2
滿足條件時要做的事情3
......
else:
不滿足條件時要做的事情1
不滿足條件時要做的事情2
不滿足條件時要做的事情3
......
例:
age = 30
print("------if判斷開始------")
if age >= 18:
print ("我已經成年了,我可以約妹子了!!!")
else:
print("還沒有成年,不能約妹子!!!")
print ("------if判斷結束------")
結果1:年齡大于18
------if判斷開始------
我已經成年了,我可以約妹子了!!!
------if判斷結束------
結果2:年齡小于18
------if判斷開始------
還沒有成年,不能約妹子!!!
------if判斷結束------
7.3 elif
elif的使用格式如下:
if xxx1:
事情1
elif xxx2:
事情2
elif xxx3:
事情3
說明:
- 當xxx1滿足時,執行事情1,然后整個if結束
- 當xxx1不滿足時,那么判斷xxx2,如果xxx2滿足,則執行事情2,然后整個if結束
- 當xxx1不滿足時,xxx2也不滿足,如果xxx3滿足,則執行事情3,然后整個if結束
例:
score = 66
if 90 <= score <= 100:
print('本次考試,等級為A')
elif 80 <= score < 90:
print('本次考試,等級為B')
elif 70 <= score < 80:
print('本次考試,等級為C')
elif 60 <= score < 70:
print('本次考試,等級為D')
elif 0 <= score < 60:
print('本次考試,等級為E')
可以和else一起使用
if 性別為男性:
輸出男性的特征
...
elif 性別為女性:
輸出女性的特征
...
else:
第三種性別的特征
...
說明:
-
當 “性別為男性” 滿足時,執行 “輸出男性的特征”的相關代碼
-
當 “性別為男性” 不滿足時,如果 “性別為女性”滿足,則執行 “輸出女性的特征”的相關代碼
-
當 “性別為男性” 不滿足,“性別為女性”也不滿足,那么久默認執行else后面的代碼,即 “第三種性別的特征”相關代碼
-
elif必須和if一起使用,否則出錯
7.4 if嵌套
if嵌套的格式
if 條件1:
滿足條件1 做的事情1
滿足條件1 做的事情2
......
if 條件2:
滿足條件2 做的事情1
滿足條件2 做的事情2
......
- 說明
- 外層的if判斷,也可以是if-else
- 內層的if判斷,也可以是if-else
- 根據實際開發的情況,進行選擇
if嵌套的應用舉例:
age = 16
girl = False
if age >= 18:
print("我已經成年了,我可以約妹子了!!!")
if girl:
print("有女朋友,去約會!!")
else:
print("沒有女朋友,約個屁啊!!")
else:
print("還沒有成年,不能約妹子!!!")
if girl:
print("還沒有成年,這是早戀啊!!")
else:
print("聽話的好孩子!!!")
結果1:age= 30;girl= True
我已經成年了,我可以約妹子了!!!
有女朋友,去約會!!
結果2:age= 30;girl= False
我已經成年了,我可以約妹子了!!!
沒有女朋友,約個屁啊!!
結果3:age= 16;girl= False
還沒有成年,不能約妹子!!!
聽話的好孩子!!!
結果4:age= 16;girl= True
還沒有成年,不能約妹子!!!
還沒有成年,這是早戀啊!!
8 回圈、break和continue
8.1 while回圈
while 條件:
條件滿足時,做的事情1
條件滿足時,做的事情2
條件滿足時,做的事情3
...(省略)...
例:
i = 0
while i < 5:
print("當前是第%d次執行回圈" % (i + 1))
print("i=%d" % i)
i += 1
結果:
當前是第1次執行回圈
i=0
當前是第2次執行回圈
i=1
當前是第3次執行回圈
i=2
當前是第4次執行回圈
i=3
當前是第5次執行回圈
i=4
案例1. 計算1~100的累積和(包含1和100)
參考代碼如下:
# encoding=utf-8
i = 1
sum = 0
while i <= 100:
sum = sum + i
i += 1
print("1~100的累積和為:%d" % sum)
運行結果:1~100的累積和為:5050
案例2. 計算1~100之間偶數的累積和(包含1和100)
# encoding=utf-8
i = 1
sum = 0
while i <= 100:
if i % 2 == 0:
sum = sum + i
i += 1
print("1~100的偶數累積和為:%d" % sum)
運行結果:1~100的偶數累積和為:2550
8.2 while回圈嵌套
類似if的嵌套,while嵌套就是:while里面還有while
格式如下
while 條件1:
條件1滿足時,做的事情1
條件1滿足時,做的事情2
......
while 條件2:
條件2滿足時,做的事情1
條件2滿足時,做的事情2
條件2滿足時,做的事情3
...(省略)...
案例1 要求:列印如下圖形:
*
* *
* * *
* * * *
* * * * *
參考代碼:
i = 1
while i<=5:
j = 1
while j<=i:
print("* ",end='')
j+=1
print("\n")
i+=1
案例2 :九九乘法表
i = 1
while i<=9:
j=1
while j<=i:
print("%d*%d=%-2d "%(j,i,i*j),end='')
j+=1
print('\n')
i+=1
運行結果:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
8.3 for回圈
像while回圈一樣,for可以完成回圈的功能,
在Python中 for回圈可以遍歷任何序列的專案,如一個串列或者一個字串等,
格式如下:
for 臨時變數 in 串列或者字串等:
回圈滿足條件時執行的代碼
else:
回圈不滿足條件時執行的代碼
例1:
name = 'AIHao'
for x in name:
print(x)
運行結果如下:
A
I
H
a
o
案例2:
name = ''
for x in name:
print(x)
else:
print("沒有資料")
運行結果如下:
沒有資料
8.5 break
1) for回圈
name = 'AIHao'
for x in name:
print('----')
if x == 'a':
break
print(x)
運行結果:
----
A
----
I
----
H
----
2)while回圈
i = 0
while i<10:
i = i+1
print('----')
if i==5:
break
print(i)
運行結果:
----
1
----
2
----
3
----
4
----
**總結:**break的作用:用來結束整個回圈
8.6 continue
1) for回圈
name = 'AIHao'
for x in name:
print('----')
if x == 'a':
continue
print(x)
運行結果:
----
A
----
I
----
H
----
----
o
2) while回圈
i = 0
while i<10:
i = i+1
print('----')
if i==5:
continue
print(i)
運行結果:
----
1
----
2
----
3
----
4
----
----
6
----
7
----
8
----
9
----
10
**總結:**continue的作用:用來結束本次回圈,緊接著執行下一次的回圈
注:
- break/continue只能用在回圈中,除此以外不能單獨使用
- break/continue在嵌套回圈中,只對最近的一層回圈起作用
9 字串、串列、元組、字典
9.1 字串
1)使用單引號或雙引號定義的資料就是字串,例:
a='hello'
或者
a="hello"
2)字串的輸出使用print()
name = 'AI浩'
position = '演算法工程師'
address = '北京石景山'
print('--------------------------------------------------')
print("姓名:%s" % name)
print("職位:%s" % position)
print("公司地址:%s" % address)
print('--------------------------------------------------')
運行結果:
--------------------------------------------------
姓名:AI浩
職位:演算法工程師
公司地址:北京石景山
--------------------------------------------------
3)字串輸入
userName = input('請輸入用戶名:')
print("用戶名為:%s" % userName)
password = input('請輸入密碼:')
print("密碼為:%s" % password)
結果:(根據輸入的不同結果也不同)
請輸入用戶名:dfsdfsd
用戶名為:dfsdfsd
請輸入密碼:qqq
密碼為:qqq
4)下標和切片
下標的使用
name = 'abcdef'
print(name[0])
print(name[1])
print(name[2])
運行結果:
a
b
c
切片:
切片是指對操作的物件截取其中一部分的操作,字串、串列、元組都支持切片操作,
切片的語法:[起始:結束:步長]
注意:選取的區間屬于左閉右開型,即從"起始"位開始,到"結束"位的前一位結束(不包含結束位本身),
name = 'abcdef'
print(name[0:3]) # 取 下標0~2 的字符
運行結果:
abc
9.2 字串常見操作
如有字串mystr = 'hello world AIHao and CSDN',以下是常見的操作
9.2.1 find
檢測 str 是否包含在 mystr中,如果是回傳開始的索引值,否則回傳-1,語法:
mystr.find(str, start=0, end=len(mystr))
例:
mystr = 'hello world AIHao and CSDN'
print(mystr.find("AIHao", 0, len(mystr)))
運行結果:
12
9.2.2 index
跟find()方法一樣,只不過如果str不在 mystr中會報一個例外,語法:
mystr.index(str, start=0, end=len(mystr))
例:
mystr = 'hello world AIHao and CSDN'
print(mystr.index("Hao", 0, len(mystr)))
運行結果:
14
9.2.3 count
回傳 str在start和end之間 在 mystr里面出現的次數,語法:
mystr.count(str, start=0, end=len(mystr))
例:
mystr = 'hello world AIHao and CSDN'
print(mystr.count("a", 0, len(mystr)))
運行結果:2
9.2.4 replace
把 mystr 中的 str1 替換成 str2,如果 count 指定,則替換不超過 count 次,語法:
mystr.replace(str1, str2, mystr.count(str1))
例:
mystr = 'hello world AIHao and CSDN'
newStr=mystr.replace("a","ee",mystr.count("a"))
print(newStr)
運行結果:
hello world AIHeeo eend CSDN
9.2.5 split
以 str 為分隔符切片 mystr,如果 maxsplit有指定值,則僅分隔 maxsplit 個子字串,語法:
mystr.split(str=" ", 2)
例:
mystr = 'hello world AIHao and CSDN'
newStr=mystr.split(" ",2)
print(newStr)
運行結果:
['hello', 'world', 'AIHao and CSDN']
mystr = 'hello world AIHao and CSDN'
newStr=mystr.split(" ")
print(newStr)
運行結果:
['hello', 'world', 'AIHao', 'and', 'CSDN']
9.2.6 capitalize
把字串的第一個字符大寫,其他的變成小寫,語法:
mystr.capitalize()
例:
mystr = 'hello world AIHao and CSDN'
print(mystr.capitalize())
運行結果:
Hello world aihao and csdn
9.2.7 title
把字串的每個單詞首字母大寫,其他的改成小寫,例:
mystr = 'hello world AIHao and CSDN'
print(mystr.title())
運行結果:
Hello World Aihao And Csdn
9.2.8 startswith
檢查字串是否是以 obj 開頭, 是則回傳 True,否則回傳 False
mystr.startswith(obj)
例:
mystr = 'hello world AIHao and CSDN'
ss='hello'
print(mystr.startswith(ss))
運行結果:True
9.2.9 endswith
檢查字串是否以obj結束,如果是回傳True,否則回傳 False,用法同上
mystr.endswith(obj)
9.2.10 lower
轉換 mystr 中所有大寫字符為小寫
mystr.lower()
例:
mystr = 'hello world AIHao and CSDN'
print(mystr.lower())
運行結果:
hello world aihao and csdn
9.2.11 upper
轉換 mystr 中的小寫字母為大寫,用法同上,
mystr.upper()
9.2.12 ljust
回傳一個原字串左對齊,并使用空格填充至長度 width 的新字串
mystr.ljust(width)
例:
mystr = "hello world AIHao and CSDN"
print(mystr.ljust(50))
運行結果:
hello world AIHao and CSDN
9.2.13 rjust
回傳一個原字串右對齊,并使用空格填充至長度 width 的新字串
mystr.rjust(width)
例:
mystr = "hello world AIHao and CSDN"
print(mystr.rjust(30))
運行結果:
hello world AIHao and CSDN
9.2.14 center
回傳一個原字串居中,并使用空格填充至長度 width 的新字串,用法同上,
mystr.center(width)
9.2.15 lstrip
洗掉 mystr 左邊的空白字符
mystr.lstrip()
9.2.16 rstrip
洗掉 mystr 字串末尾的空白字符
mystr.rstrip()
9.2.17 strip
洗掉mystr字串兩端的空白字符
>>> a = "\n\t itcast \t\n"
>>> a.strip()
'itcast'
9.2.18 rfind
類似于 find()函式,不過是從右邊開始查找.
mystr.rfind(str, start=0,end=len(mystr) )
9.2.19 rindex
類似于 index(),不過是從右邊開始.
mystr.rindex( str, start=0,end=len(mystr))
9.2.20 partition
把mystr以str分割成三部分,str前,str和str后
mystr.partition(str)
9.2.21 rpartition
類似于 partition()函式,不過是從右邊開始.
mystr.rpartition(str)
9.2.22 splitlines
按照行分隔,回傳一個包含各行作為元素的串列
mystr.splitlines()
9.2.23 isalpha
如果 mystr 所有字符都是字母 則回傳 True,否則回傳 False
mystr.isalpha()
9.2.24 isdigit
如果 mystr 只包含數字則回傳 True 否則回傳 False.
mystr.isdigit()
9.2.25 isalnum
如果 mystr 所有字符都是字母或數字則回傳 True,否則回傳 False
mystr.isalnum()
9.2.26 isspace
如果 mystr 中只包含空格,則回傳 True,否則回傳 False.
mystr.isspace()
9.2.27 join
mystr 中每個字符后面插入str,構造出一個新的字串
mystr.join(str)
9.3 串列List
串列list用[,…]表示,格式如下:
namesList = ['xiaoWang','xiaoZhang','xiaoHua']
9.3.1 for回圈遍歷list
1)例:
namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
for name in namesList:
print(name)
結果:
xiaoWang
xiaoZhang
xiaoHua
串列推導式
1)普通方式
a = [x for x in range(4)]
print(a)
b = [x for x in range(3, 4)]
print(b)
c = [x for x in range(3, 19)]
print(c)
d = [x for x in range(3, 19, 2)]
print(d)
運行結果:
[0, 1, 2, 3]
[3]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
[3, 5, 7, 9, 11, 13, 15, 17]
2)在回圈的程序中加入if判斷
a = [x for x in range(3, 15) if x % 2 == 0]
print(a)
b = [x for x in range(3, 15) if x % 2 != 0]
print(b)
b = [x for x in range(3, 15)]
print(b)
運行結果:
[4, 6, 8, 10, 12, 14]
[3, 5, 7, 9, 11, 13]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
3)多個for回圈
a = [(x, y) for x in range(3, 5) for y in range(3)]
print(a)
b = [(x, y, z) for x in range(3, 5) for y in range(3) for z in range(4, 6)]
print(b)
運行結果:
[(3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2)]
[(3, 0, 4), (3, 0, 5), (3, 1, 4), (3, 1, 5), (3, 2, 4), (3, 2, 5), (4, 0, 4), (4, 0, 5), (4, 1, 4), (4, 1, 5), (4, 2, 4), (4, 2, 5)]
9.3.2 while回圈遍歷list
namesList = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
length = len(namesList)
i = 0
while i < length:
print(namesList[i])
i += 1
運行結果:
xiaoWang
xiaoZhang
xiaoHua
9.4 串列的常用操作
串列中存放的資料是可以進行修改的,比如"增"、“刪”、“改”"
9.4.1 添加元素("增"append, extend, insert)
append:通過append可以向串列添加元素
例:
#定義變數A,默認有3個元素
A = ['xiaoWang','xiaoZhang','xiaoHua']
print("-----添加之前,串列A的資料-----")
for tempName in A:
print(tempName)
#提示、并添加元素
temp = input('請輸入姓名:')
A.append(temp)
print("-----添加之后,串列A的資料-----")
for tempName in A:
print(tempName)
結果:
-----添加之前,串列A的資料-----
xiaoWang
xiaoZhang
xiaoHua
請輸入姓名:xiaohei
-----添加之后,串列A的資料-----
xiaoWang
xiaoZhang
xiaoHua
xiaohei
extend:通過extend可以將另一個集合中的元素逐一添加到串列中
a = [1, 2]
b = [3, 4]
a.append(b)
print(a)
a.extend(b)
print(a)
結果:
[1, 2, [3, 4]]
[1, 2, [3, 4], 3, 4]
insert :insert(index, object) 在指定位置index前插入元素object
a = [0, 1, 2]
a.insert(1, 3)
print(a)
結果:
[0, 3, 1, 2]
9.4.2修改元素(“改”)
修改元素的時候,要通過下標來確定要修改的是哪個元素,然后才能進行修改,例:
#定義變數A,默認有3個元素
A = ['xiaoWang','xiaoZhang','xiaoHua']
print("-----修改之前,串列A的資料-----")
for tempName in A:
print(tempName)
#修改元素
A[1] = 'xiaoLu'
print("-----修改之后,串列A的資料-----")
for tempName in A:
print(tempName)
結果:
-----修改之前,串列A的資料-----
xiaoWang
xiaoZhang
xiaoHua
-----修改之后,串列A的資料-----
xiaoWang
xiaoLu
xiaoHua
9.4.3 查找元素("查"in, not in, index, count)
所謂的查找,就是看看指定的元素是否存在
in, not in
python中查找的常用方法為:
- in(存在),如果存在那么結果為true,否則為false
- not in(不存在),如果不存在那么結果為true,否則false
demo
#待查找的串列
nameList = ['xiaoWang','xiaoZhang','xiaoHua']
#獲取用戶要查找的名字
findName = input('請輸入要查找的姓名:')
#查找是否存在
if findName in nameList:
print('在字典中找到了相同的名字')
else:
print('沒有找到')
說明:
in的方法只要會用了,那么not in也是同樣的用法,只不過not in判斷的是不存在
index, count
index和count與字串中的用法相同
a = ['a', 'b', 'c', 'a', 'b']
print(a.index('a', 1, 4))
print(a.count('b'))
print(a.count('d'))
print(a.index('a', 1, 3)) # 注意是左閉右開區間
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 5, in <module>
print(a.index('a', 1, 3)) # 注意是左閉右開區間
ValueError: 'a' is not in list
3
2
0
9.4.4 洗掉元素("刪"del, pop, remove)
類比現實生活中,如果某位同學調班了,那么就應該把這個條走后的學生的姓名洗掉掉;在開發中經常會用到洗掉這種功能,
串列元素的常用洗掉方法有:
- del:根據下標進行洗掉
- pop:洗掉最后一個元素
- remove:根據元素的值進行洗掉
demo:(del)
movieName = ['加勒比海盜','駭客帝國','第一滴血','指環王','霍位元人','速度與激情']
print('------洗掉之前------')
for tempName in movieName:
print(tempName)
del movieName[2]
print('------洗掉之后------')
for tempName in movieName:
print(tempName)
結果:
------洗掉之前------
加勒比海盜
駭客帝國
第一滴血
指環王
霍位元人
速度與激情
------洗掉之后------
加勒比海盜
駭客帝國
指環王
霍位元人
速度與激情
例:(pop)
movieName = ['加勒比海盜','駭客帝國','第一滴血','指環王','霍位元人','速度與激情']
print('------洗掉之前------')
for tempName in movieName:
print(tempName)
movieName.pop()
print('------洗掉之后------')
for tempName in movieName:
print(tempName)
結果:
------洗掉之前------
加勒比海盜
駭客帝國
第一滴血
指環王
霍位元人
速度與激情
------洗掉之后------
加勒比海盜
駭客帝國
第一滴血
指環王
霍位元人
demo:(remove)
movieName = ['加勒比海盜','駭客帝國','第一滴血','指環王','霍位元人','速度與激情']
print('------洗掉之前------')
for tempName in movieName:
print(tempName)
movieName.remove('指環王')
print('------洗掉之后------')
for tempName in movieName:
print(tempName)
結果:
------洗掉之前------
加勒比海盜
駭客帝國
第一滴血
指環王
霍位元人
速度與激情
------洗掉之后------
加勒比海盜
駭客帝國
第一滴血
霍位元人
速度與激情
9.4.5 排序(sort, reverse)
sort方法是將list按特定順序重新排列,默認為由小到大,引數reverse=True可改為倒序,由大到小,
reverse方法是將list逆置,
>>> a = [1, 4, 2, 3]
>>> a
[1, 4, 2, 3]
>>> a.reverse()
>>> a
[3, 2, 4, 1]
>>> a.sort()
>>> a
[1, 2, 3, 4]
>>> a.sort(reverse=True)
>>> a
[4, 3, 2, 1]
9.4.6 串列的嵌套
類似while回圈的嵌套,串列也是支持嵌套的
一個串列中的元素又是一個串列,那么這就是串列的嵌套
schoolNames = [['北京大學','清華大學'],
['南開大學','天津大學','天津師范大學'],
['山東大學','中國海洋大學']]
案例:一個學校,有3個辦公室,現在有8位老師等待工位的分配,請撰寫程式,完成隨機的分配
#encoding=utf-8
import random
# 定義一個串列用來保存3個辦公室
offices = [[],[],[]]
# 定義一個串列用來存盤8位老師的名字
names = ['A','B','C','D','E','F','G','H']
i = 0
for name in names:
index = random.randint(0,2)
offices[index].append(name)
i = 1
for tempNames in offices:
print('辦公室%d的人數為:%d'%(i,len(tempNames)))
i+=1
for name in tempNames:
print("%s"%name,end='')
print("\n")
print("-"*20)
運行結果如下:
辦公室1的人數為:3
BFG
--------------------
辦公室2的人數為:5
ACDEH
--------------------
辦公室3的人數為:0
--------------------
9.5 元組
Python的元組與串列類似,不同之處在于元組的元素不能修改,元組使用小括號(),串列使用方括號[],例:
aTuple = ('et',77,99.9)
print(aTuple)
運行結果:(‘et’, 77, 99.9)
9.5.1 訪問元組
aTuple = ('et',77,99.9)
print(aTuple[0])
print(aTuple[1])
運行結果:
et
77
9.5.2 修改元組
aTuple = ('et',77,99.9)
aTuple[0]=111
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 2, in <module>
aTuple[0]=111
TypeError: 'tuple' object does not support item assignment
從上面的運行結果可以得出: python中不允許修改元組的資料,包括不能洗掉其中的元素,
9.5.3 元組的內置函式count, index
index和count與字串和串列中的用法相同
>>> a = ('a', 'b', 'c', 'a', 'b')
>>> a.index('a', 1, 3) # 注意是左閉右開區間
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: tuple.index(x): x not in tuple
>>> a.index('a', 1, 4)
3
>>> a.count('b')
2
>>> a.count('d')
0
9.6 字典
字典是一種可變容器模型,且可存盤任意型別物件,
字典的每個鍵值 key=>value 對用冒號 : 分割,每個對之間用逗號(,)分割,整個字典包括在花括號 {} 中 ,格式如下所示:
d = {key1 : value1, key2 : value2, key3 : value3 }

例:
info = {'name':'AI浩', 'id':100, 'sex':'f', 'address':'中國北京'}
9.6.1 根據鍵訪問值
info = {'name':'AI浩', 'id':100, 'sex':'f', 'address':'中國北京'}
print(info['name'])
print(info['address'])
結果:
AI浩
中國北京
若訪問不存在的鍵,則會報錯:
info = {'name': 'AI浩', 'id': 100, 'sex': 'f', 'address': '中國北京'}
print(info['age'])
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 2, in <module>
print(info['age'])
KeyError: 'age'
在我們不確定字典中是否存在某個鍵而又想獲取其值時,可以使用get方法,還可以設定默認值:
>>> age = info.get('age')
>>> age #'age'鍵不存在,所以age為None
>>> type(age)
<type 'NoneType'>
>>> age = info.get('age', 18) # 若info中不存在'age'這個鍵,就回傳默認值18
>>> age
18
9.7 字典的常用操作
9.7.1 修改元素
字典的每個元素中的資料是可以修改的,只要通過key找到,即可修改,例:
info = {'name': 'AI浩', 'id': 100, 'sex': 'f', 'address': '中國北京'}
info['id'] = 150
print('修改之后的id為:%d' % info['id'])
結果:修改之后的id為:150
9.7.2 添加元素
使用 變數名[‘鍵’] = 資料 時,這個“鍵”在字典中,不存在,那么就會新增這個元素,例:
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
newId = input('請輸入新的ID')
info['id'] = int(newId)
print('添加之后的id為:%d' % info['id'])
結果:
請輸入新的ID123
添加之后的id為:123
9.7.3 洗掉元素
對字典進行洗掉操作,有一下幾種:
- del
- clear()
例1:del洗掉指定的元素
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
print('洗掉前,%s' % info['name'])
del info['name']
print('洗掉后,%s' % info['name'])
結果:
洗掉前,AI浩
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 4, in <module>
print('洗掉后,%s' % info['name'])
KeyError: 'name'
例2:del洗掉整個字典
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
print('洗掉前,%s' % info)
del info
print('洗掉后,%s' % info)
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 4, in <module>
print('洗掉后,%s' % info)
NameError: name 'info' is not defined
洗掉前,{'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
例3:clear清空整個字典
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
print('清空前,%s' % info)
info.clear()
print('清空后,%s' % info)
運行結果:
清空前,{'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
清空后,{}
9.7.4 字典的長度
使用len()方法,求字典的長度,例:
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
print('字典的長度:%d' % len(info))
運行結果:字典的長度:3
9.7.5 找出字典中的所有key
keys回傳一個包含字典所有KEY的視圖物件,例:
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
dicKeys=info.keys()
print(dicKeys)
print(dicKeys[0])
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 4, in <module>
print(dicKeys[0])
TypeError: 'dict_keys' object is not subscriptable
dict_keys(['name', 'sex', 'address'])
注:回傳的是個視圖物件,不是list,很多資料說list是不對的,但是可以轉為list,例:
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
dicKeys=list(info.keys())
print(dicKeys)
print(dicKeys[0])
運行結果:
['name', 'sex', 'address']
name
9.7.6 找出字典所有的value
屬性values回傳一個包含字典所有value的視圖串列,用法同上,例:
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
dicvalues=list(info.values())
print(dicvalues)
print(dicvalues[0])
運行結果:
['AI浩', 'f', '中國北京']
AI浩
9.7.7 找出字典的(鍵,值)
屬性items,回傳一個包含所有(鍵,值)元祖的串列
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
dicItems=info.items()
print(dicItems)
運行結果:
dict_items([('name', 'AI浩'), ('sex', 'f'), ('address', '中國北京')])
9.7.8 判斷key是否存在
“key in dict"如果鍵在字典dict里回傳true,否則回傳false,例:
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
ss='name' in info
print(ss)
運行結果:True
9.7.9 遍歷字典的幾種方式
1) 遍歷字典的key(鍵)
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
for key in info.keys():
print(key)
運行結果:
name
sex
address
2) 遍歷字典的value(值)
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
for key in info.values():
print(key)
運行結果:
AI浩
f
中國北京
3) 遍歷字典的項(元素)
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
for item in info.items():
print(item)
運行結果:
('name', 'AI浩')
('sex', 'f')
('address', '中國北京')
4) 遍歷字典的key-value(鍵值對)
info = {'name': 'AI浩', 'sex': 'f', 'address': '中國北京'}
for key, value in info.items():
print("key=%s,value=%s" % (key, value))
運行結果:
key=name,value=AI浩
key=sex,value=f
key=address,value=中國北京
10 函式
函式是組織好的,可重復使用的,用來實作單一,或相關聯功能的代碼段,
函式能提高應用的模塊性,和代碼的重復利用率,你已經知道Python提供了許多內建函式,比如print(),但你也可以自己創建函式,這被叫做用戶自定義函式,
10.1 定義函式
語法:
def 函式名(引數串列):
函式體
例:
# 定義一個函式,能夠完成列印資訊的功能
def printInfo():
print ('------------------------------------')
print (' 人生苦短,我用Python')
print ('------------------------------------')
定義函式的規則:
- 函式代碼塊以 def 關鍵詞開頭,后接函式識別符號名稱和圓括號 (),
- 任何傳入引數和自變數必須放在圓括號中間,圓括號之間可以用于定義引數,
- 函式的第一行陳述句可以選擇性地使用檔案字串—用于存放函式說明,
- 函式內容以冒號 : 起始,并且縮進,
- return [運算式] 結束函式,選擇性地回傳一個值給呼叫方,不帶運算式的 return 相當于回傳 None,
10.2 呼叫函式
定義了函式之后,就相當于有了一個具有某些功能的代碼,想要讓這些代碼能夠執行,需要呼叫它
呼叫函式很簡單的,通過 函式名() 即可完成呼叫,例:
# 定義完函式后,函式是不會自動執行的,需要呼叫它才可以
printInfo()
10.3 函式的注釋
在函式定義下面使用'''進行注釋,使用help函式可以查看函式的注釋,
def test(a1, a2):
'''
用來完成對2個數求和"
:param a1:第一個引數
:param a2:第二個引數
:return:無
'''
print("%d" % (a1 + a2))
print(help(test))
運行結果:
test(a1, a2)
用來完成對2個數求和"
:param a1:第一個引數
:param a2:第二個引數
:return:無
None
10.4 函式的引數
10.4.1 引數的定義
? 引數分形參、實參
形參:函式定義時括號內的引數
實參:函式呼叫時括號內的引數
形參相當于變數,實參相當于變數的值,
def add2num(a, b):
c = a + b
print(c)
add2num(11, 22) # 呼叫帶有引數的函式時,需要在小括號中,傳遞資料
a,b為形參;11,12為實參
形參:
只在被呼叫時,才分配記憶體單元,呼叫結束,立刻釋放所分配的記憶體,
只在函式內部有效,
實參:
可以是:常量、變數、運算式、函式,
進行函式呼叫時,實參必須是確定的值,
10.4.2 引數的分類
Python的函數除了正常定義的必選引數外,還可以使用默認引數、可變引數和關鍵字引數,使得函式定義出來的介面,不但能處理復雜的引數,還可以簡化呼叫者的代碼,
1)位置引數
位置形參:函式定義時,從左往右寫的引數,比如上面的 a, b
位置實參:函式呼叫時,從左往右寫的引數, 比如上面的 11,12
位置形參定義多少個,呼叫時位置實參必須寫上多少個,多一個少一個都不行,
2)關鍵引數:
正常情況下,給函式傳引數,要按順序,如果不想按順序,就用關鍵引數,
指定引數名的引數,就叫做關鍵引數,
函式呼叫時:func(a=1, b=2), 這種指定了引數名的引數,就是關鍵引數,
呼叫函式時,關鍵引數可以和位置引數一起用,但是關鍵引數必須在位置引數的后面,不然會報錯,
例:
def add2num(a, b):
c = a + b
print(c)
#正確的呼叫方式
add2num(11, b=22) # 呼叫帶有引數的函式時,需要在小括號中,傳遞資料
add2num(a=11, b=22)
add2num(b=11, a=22)
# 錯誤的呼叫方式,
#add2num(22, a=22)
#add2num(b=11,22)
3)默認引數
函式定義時,默認引數必須在位置形參的后面,
函式呼叫時,指定引數名的引數,叫關鍵引數,
而在函式定義時,給引數名指定值的時候,這個引數叫做默認引數,
關鍵引數,和默認引數兩個引數寫法一樣,區別在于:
關鍵引數是在函式呼叫時,指定實參的引數名,也可以說指定值的引數名,
默認引數是在函式定義時,指定引數名的值,
定義時,有默認引數的話,呼叫時,這個實參可以不寫,如果實參不寫的話,這個形參的引數值是他的默認值,
例:
def add2num(a, b=100):
c = a + b
print(c)
add2num(11, b=22) # 呼叫帶有引數的函式時,需要在小括號中,傳遞資料
add2num(11)
運行結果:
33
111
4 ) 動態引數:*args **kwargs
*args
針對函式定義時的*:
def func(a, b, *args):
pass
*args會接收函式呼叫時,傳入的多余的位置實參,
*args 是一個元組
例子:
func(1, 2, 3, 4, 5, 6) 函式呼叫,因為函式定義時,*args前面有形參a, 形參b, *args就接收呼叫時多余的位置實參
a為1, b為2, *args 為: (3, 4, 5, 6),是一個元組,
針對函式呼叫時的 *:
func(1, 2, *[1, 2, 3, 4]) == func(1, 2, 1, 2, 3, 4)
函式呼叫時有*, 就應該立馬將*后面的串列,元組,字串之類的迭代器,打散成位置引數來看,
注意,如果 *后面是一個字典的話,那么打散成的位置引數就是字典的key
*可以看做是for回圈,
形參中 *args 只能接收多余的位置實參,成為一個元組,不能接收關鍵實參,
例:
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
nums = [1, 2, 3]
# 呼叫方式1
print(calc(nums[0], nums[1], nums[2]))
#呼叫方式2
print(calc(*nums))
運行結果:
14
14
**kwargs:
針對函式定義時,站在形參的角度看 **:
接收多余的關鍵實參,成為一個字典dict,
字典的key是關鍵實參的變數名,字典的value是關鍵實參的值,
將字典交給**后面的變數名,這里是kwargs
站在實參的角度看 ** :
d = {‘x’:1, ‘y’:2, ‘z’:333}
func(**d) # 等價于func(x=1,y=2,z=333)
函式呼叫時,后面可以接一個字典,然后會把字典打散成關鍵引數的形式,也就是key=value的形式,
例:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
#呼叫方式1
print(person('Michael', 30))
#呼叫方式2
print(person('Bob', 35, city='Beijing'))
#呼叫方式3
print(person('Adam', 45, gender='M', job='Engineer'))
運行結果:
name: Michael age: 30 other: {}
None
name: Bob age: 35 other: {'city': 'Beijing'}
None
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
None
5)混合引數時,引數順序
函式定義時:
從左往右:位置形參 > *args > 默認引數 > **kwargs
位置形參 > 默認引數 > *args > **kwargs 也可以,
因為函式呼叫時給的實參滿足了位置形參、默認引數之后,會把多余的位置實參給args,這樣并不會報錯,
但是 **kwargs 必須在 *args后面
默認形參必須在位置形參后面
? 函式呼叫時:
從左到右:位置實參 > *args > 關鍵引數 > **kwargs
因為 * args 在函式呼叫時,會被打散成位置實參,而關鍵引數必須在位置實參的后面,否則會報錯,SyntaxError: positional argument follows keyword argument
*args 必須在 **kwargs后面, 否則會報語法錯誤:SyntaxError: iterable argument unpacking follows keyword argument unpacking
總結
Python的函式具有非常靈活的引數形態,既可以實作簡單的呼叫,又可以傳入非常復雜的引數,
默認引數一定要用不可變物件,如果是可變物件,程式運行時會有邏輯錯誤!
要注意定義可變引數和關鍵字引數的語法:
*args是可變引數,args接收的是一個tuple;
**kw是關鍵字引數,kw接收的是一個dict,
以及呼叫函式時如何傳入可變引數和關鍵字引數的語法:
可變引數既可以直接傳入:func(1, 2, 3),又可以先組裝list或tuple,再通過*args傳入:func(*(1, 2, 3));
關鍵字引數既可以直接傳入:func(a=1, b=2),又可以先組裝dict,再通過**kw傳入:func(**{'a': 1, 'b': 2}),
使用*args和**kw是Python的習慣寫法,當然也可以用其他引數名,但最好使用習慣用法,
命名的關鍵字引數是為了限制呼叫者可以傳入的引數名,同時可以提供默認值,
定義命名的關鍵字引數在沒有可變引數的情況下不要忘了寫分隔符*,否則定義的將是位置引數,
10.4.3 引數的傳遞
Python引數傳遞采用的肯定是“傳物件參考”的方式,這種方式相當于傳值和傳參考的一種綜合,如果函式收到的是一個可變物件(比如字典或者串列)的參考,就能修改物件的原始值--相當于通過“傳參考”來傳遞物件,如果函式收到的是一個不可變物件(比如數字、字符或者元組)的參考,就不能直接修改原始物件--相當于通過“傳值’來傳遞物件,
例:
attrList = [0, 1, 2, 3, 4, 5]
print("改變前————————————————————————————————")
print(attrList)
def func(i, attrList):
attrList[i] = attrList[i] * 10
print("改變后————————————————————————————————")
for i in range(3):
func(i, attrList)
print(attrList)
運行結果:
改變前————————————————————————————————
[0, 1, 2, 3, 4, 5]
改變后————————————————————————————————
[0, 10, 20, 3, 4, 5]
可以看到,List發生了改變,如果傳入不可變的元素呢?
a = 10
print("改變前————————————————————————————————")
print(a)
def func(c):
print(id(c))
c += 2
print(id(c))
print("func函式的c值:", c)
print(id(a))
func(a)
print("改變后————————————————————————————————")
print(a)
print(id(a))
運行結果:
改變前————————————————————————————————
10
140724141828160
140724141828160
140724141828224
func函式的c值: 12
改變后————————————————————————————————
10
140724141828160
將a變數作為引數傳遞給了func函式,傳遞了a的一個參考,把a的地址傳遞過去了,所以在函式內獲取的變數c的地址跟變數a的地址是一樣的,但是在函式內,對c進行賦值運算,c的值從10變成了12,實際上10和12所占的記憶體空間都還是存在的,賦值運算后,c指向12所在的記憶體,而a仍然指向10所在的記憶體,所以后面列印a,其值還是10.
10.5 函式的回傳值
想要在函式中把結果回傳給呼叫者,需要在函式中使用return,例:
def add2num(a, b):
c = a + b
return c
print(add2num(1, 2))
可以回傳多個回傳值,例:
def divid(a, b):
shang = a // b
yushu = a % b
return shang, yushu
sh, yu = divid(5, 2)
10.6 區域變數與全域變數
-
區域變數就是定義在一個函式體內部的變數
-
全域變數是定義在外面的變數
例:
a = 1 def f(): b = 2其中a就是全域變數,而b是區域變數,區域變數只在函式體內部有效,出了函式體,外面是訪問不到的,而全域變數則對下面的代碼都有效,
全域變數可以直接在函式體內容部使用的,你可以直接訪問,但是注意的是,如果對于不可變型別的資料,如果在函式里面進行了賦值操作,則對外面的全域變數不產生影響,因為相當于新建了一個區域變數,只是名字和全域一樣,而對于可變型別,如果使用賦值陳述句,同樣對外部不產生影響,但是使用方法的話就會對外部產生影響,
g_b = 3 g_l1 = [1, 2] g_l2 = [1, 2, 3] def t1(): g_b = 2 g_l1 = [] g_l2.append(7) t1() print(g_b, g_l1, g_l2)運行結果:3 [1, 2] [1, 2, 3, 7]
global關鍵字
上面說到,如果使用的是賦值陳述句,在函式內部相當于新建了一個變數,并且重新給了指向,但是有時候我們想把這個變數就是外部的那個全域變數,在賦值操作的時候,就是對全域變數給了重新的指向,這個時候可以通過global關鍵字表示我在函式里面的這個變數是使用的全域那個,使用方法如下:
g_b = 3
def t1():
global g_b
g_b = 2
t1()
print(g_b)
運行結果:2
這個時候你會發現全域變數g_b也重新指向了,這是因為global g_b表示指定了函式中的g_b就是外面的那個,
10.7 遞回函式
如果一個函式在內部呼叫自身本身,這個函式就是遞回函式,例:
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
print(fact(5))
運行結果:120
可以根據函式定義看到計算程序如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
遞回函式的優點是定義簡單,邏輯清晰,理論上,所有的遞回函式都可以寫成回圈的方式,但回圈的邏輯不如遞回清晰,
使用遞回函式需要注意防止堆疊溢位,在計算機中,函式呼叫是通過堆疊(stack)這種資料結構實作的,每當進入一個函式呼叫,堆疊就會加一層堆疊幀,每當函式回傳,堆疊就會減一層堆疊幀,由于堆疊的大小不是無限的,所以,遞回呼叫的次數過多,會導致堆疊溢位,可以試試fact(1000),
解決遞回呼叫堆疊溢位的方法是通過尾遞回優化,事實上尾遞回和回圈的效果是一樣的,所以,把回圈看成是一種特殊的尾遞回函式也是可以的,
尾遞回是指,在函式回傳的時候,呼叫自身本身,并且,return陳述句不能包含運算式,這樣,編譯器或者解釋器就可以把尾遞回做優化,使遞回本身無論呼叫多少次,都只占用一個堆疊幀,不會出現堆疊溢位的情況,
上面的fact(n)函式由于return n * fact(n - 1)引入了乘法運算式,所以就不是尾遞回了,要改成尾遞回方式,需要多一點代碼,主要是要把每一步的乘積傳入到遞回函式中,例:
def fact(n):
return fact_iter(n, 1)
def fact_iter(num, product):
if num == 1:
return product
return fact_iter(num - 1, num * product)
可以看到,return fact_iter(num - 1, num * product)僅回傳遞回函式本身,num - 1和num * product在函式呼叫前就會被計算,不影響函式呼叫,
fact(5)對應的fact_iter(5, 1)的呼叫如下:
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
尾遞回呼叫時,如果做了優化,堆疊不會增長,因此,無論多少次呼叫也不會導致堆疊溢位,
遺憾的是,大多數編程語言沒有針對尾遞回做優化,Python解釋器也沒有做優化,所以,即使把上面的fact(n)函式改成尾遞回方式,也會導致堆疊溢位,
小結
使用遞回函式的優點是邏輯簡單清晰,缺點是過深的呼叫會導致堆疊溢位,
針對尾遞回優化的語言可以通過尾遞回防止堆疊溢位,尾遞回事實上和回圈是等價的,沒有回圈陳述句的編程語言只能通過尾遞回實作回圈,
Python標準的解釋器沒有針對尾遞回做優化,任何遞回函式都存在堆疊溢位的問題,
10.8 匿名函式
10.8.1 定義
用lambda關鍵詞能創建小型匿名函式,這種函式得名于省略了用def宣告函式的標準步驟,
lambda函式的語法只包含一個陳述句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
如下實體:
sum = lambda a1, a2: a1 * a2
# 呼叫sum函式
print("Value of total : ", sum(10, 20))
print("Value of total : ", sum(20, 20))
以上實體輸出結果:
Value of total : 200
Value of total : 400
Lambda函式能接收任何數量的引數但只能回傳一個運算式的值
匿名函式不能直接呼叫print,因為lambda需要一個運算式
10.8.2 應用場合
例1:自己定義函式作為引數傳遞
def fun(a, b, opt):
print("a =", a)
print("b =", b)
print("result =", opt(a, b))
fun(1, 2, lambda x, y: x + y)
運行結果:
a = 1
b = 2
result = 3
例2:作為內置函式的引數
想一想,下面的資料如何指定按age或name排序?
stus = [
{"name":"zhangsan", "age":18},
{"name":"lisi", "age":19},
{"name":"wangwu", "age":17}
]
按name排序:
stus.sort(key=lambda x: x['name'])
print(stus)
運行結果:
[{'name': 'lisi', 'age': 19}, {'name': 'wangwu', 'age': 17}, {'name': 'zhangsan', 'age': 18}]
按age排序:
stus.sort(key=lambda x: x['age'])
print(stus)
運行結果:
[{'name': 'wangwu', 'age': 17}, {'name': 'zhangsan', 'age': 18}, {'name': 'lisi', 'age': 19}]
11 檔案操作
11.1 打開與關閉
11.1.1 打開檔案
在python,使用open函式,可以打開一個已經存在的檔案,或者創建一個新檔案
open(檔案名,訪問模式)
示例如下:
f = open('test.txt', 'w')
說明:
| 訪問模式 | 說明 |
|---|---|
| r | 以只讀方式打開檔案,檔案的指標將會放在檔案的開頭,這是默認模式, |
| w | 打開一個檔案只用于寫入,如果該檔案已存在則將其覆寫,如果該檔案不存在,創建新檔案, |
| a | 打開一個檔案用于追加,如果該檔案已存在,檔案指標將會放在檔案的結尾,也就是說,新的內容將會被寫入到已有內容之后,如果該檔案不存在,創建新檔案進行寫入, |
| rb | 以二進制格式打開一個檔案用于只讀,檔案指標將會放在檔案的開頭,這是默認模式, |
| wb | 以二進制格式打開一個檔案只用于寫入,如果該檔案已存在則將其覆寫,如果該檔案不存在,創建新檔案, |
| ab | 以二進制格式打開一個檔案用于追加,如果該檔案已存在,檔案指標將會放在檔案的結尾,也就是說,新的內容將會被寫入到已有內容之后,如果該檔案不存在,創建新檔案進行寫入, |
| r+ | 打開一個檔案用于讀寫,檔案指標將會放在檔案的開頭, |
| w+ | 打開一個檔案用于讀寫,如果該檔案已存在則將其覆寫,如果該檔案不存在,創建新檔案, |
| a+ | 打開一個檔案用于讀寫,如果該檔案已存在,檔案指標將會放在檔案的結尾,檔案打開時會是追加模式,如果該檔案不存在,創建新檔案用于讀寫, |
| rb+ | 以二進制格式打開一個檔案用于讀寫,檔案指標將會放在檔案的開頭, |
| wb+ | 以二進制格式打開一個檔案用于讀寫,如果該檔案已存在則將其覆寫,如果該檔案不存在,創建新檔案, |
| ab+ | 以二進制格式打開一個檔案用于追加,如果該檔案已存在,檔案指標將會放在檔案的結尾,如果該檔案不存在,創建新檔案用于讀寫, |
11.1.2 關閉檔案
close( )
示例如下:
# 新建一個檔案,檔案名為:test.txt
f = open('test.txt', 'w')
# 關閉這個檔案
f.close()
11.2 檔案的讀寫
11.2.1 寫資料(write)
使用write()可以完成向檔案寫入資料,例:
f = open('test.txt', 'w')
f.write('hello 大家好, 我是AI浩')
f.close()
運行現象:

注意:
- 如果檔案不存在那么創建,如果存在那么就先清空,然后寫入資料
11.2.2 讀資料(read)
使用read(num)可以從檔案中讀取資料,num表示要從檔案中讀取的資料的長度(單位是位元組),如果沒有傳入num,那么就表示讀取檔案中所有的資料,例:
f = open('test.txt', 'r')
content = f.read(5)
print(content)
print("-"*30)
content = f.read()
print(content)
f.close()
運行結果:
hello
------------------------------
大家好, 我是AI浩
注意:
- 如果open是打開一個檔案,那么可以不用謝打開的模式,即只寫
open('test.txt') - 如果使用讀了多次,那么后面讀取的資料是從上次讀完后的位置開始的
11.2.3 讀資料(readlines)
就像read沒有引數時一樣,readlines可以按照行的方式把整個檔案中的內容進行一次性讀取,并且回傳的是一個串列,其中每一行的資料為一個元素
#coding=utf-8
f = open('test.txt', 'r')
content = f.readlines()
print(type(content))
i=1
for temp in content:
print("%d:%s"%(i, temp))
i+=1
f.close()
運行結果:
<class 'list'>
1:hello 大家好, 我是AI浩
11.2.4 讀資料(readline)
#coding=utf-8
f = open('test.txt', 'r')
content = f.readline()
print("1:%s"%content)
content = f.readline()
print("2:%s"%content)
f.close()
運行結果:
1:hello 大家好, 我是AI浩
2:asfsifhiudh
11.3 檔案的常用操作
11.3.1 獲取當前讀寫的位置
在讀寫檔案的程序中,如果想知道當前的位置,可以使用tell()來獲取,例:
# 打開一個已經存在的檔案
f = open("test.txt", "r")
str = f.read(3)
print("讀取的資料是 : ", str)
# 查找當前位置
position = f.tell()
print("當前檔案位置 : ", position)
str = f.read(3)
print("讀取的資料是 : ", str)
# 查找當前位置
position = f.tell()
print("當前檔案位置 : ", position)
f.close()
運行結果:
讀取的資料是 : hel
當前檔案位置 : 3
讀取的資料是 : lo
當前檔案位置 : 6
11.3.2 定位到某個位置
如果在讀寫檔案的程序中,需要從另外一個位置進行操作的話,可以使用seek()
seek(offset, from)有2個引數
- offset:偏移量
- from:方向
- 0:表示檔案開頭
- 1:表示當前位置
- 2:表示檔案末尾
例1:把位置設定為:從檔案開頭,偏移5個位元組
# 打開一個已經存在的檔案
f = open("test.txt", "r")
str = f.read(30)
print("讀取的資料是 : ", str)
# 查找當前位置
position = f.tell()
print("當前檔案位置 : ", position)
# 重新設定位置
f.seek(5, 0)
# 查找當前位置
position = f.tell()
print("當前檔案位置 : ", position)
f.close()
例2:把位置設定為:離檔案末尾,3位元組處
# 打開一個已經存在的檔案
f = open("test.txt", "rb")
print("讀取的資料是 : ", str)
position = f.tell()
print("當前檔案位置 : ", position)
# 重新設定位置
f.seek(-3, 2)
# 讀取到的資料為:檔案最后3個位元組資料
str = f.read()
print("讀取的資料是 : ", str)
f.close()
運行結果:
讀取的資料是 : <class 'str'>
當前檔案位置 : 0
讀取的資料是 : b'ddf'
11.3.3 檔案重命名
os模塊中的rename()可以完成對檔案的重命名操作
rename(需要修改的檔案名, 新的檔案名)
import os
os.rename("test.txt", "test-1.txt")
11.3.4 洗掉檔案
os模塊中的remove()可以完成對檔案的洗掉操作
remove(待洗掉的檔案名)
import os
os.remove("test.txt")
11.4 檔案夾的相關操作
實際開發中,有時需要用程式的方式對檔案夾進行一定的操作,比如創建、洗掉等
就像對檔案操作需要os模塊一樣,如果要操作檔案夾,同樣需要os模塊
11.4.1 創建檔案夾
import os
os.mkdir("aa")
11.4.2 獲取當前目錄
import os
os.getcwd()
11.4.3 改變默認目錄
import os
os.chdir("../")
11.4.4 獲取目錄串列
import os
os.listdir("./")
11.4.5 洗掉檔案夾
import os
os.rmdir("張三")
11.4.6 檢測檔案夾是否存在
import os
if not os.path.exists(path):
os.makedirs(path)
11.4.7 創建多級檔案夾
import os
os.makedirs(opDir)
12 面向物件編程
面向物件編程——Object Oriented Programming,簡稱OOP,是一種程式設計思想,OOP把物件作為程式的基本單元,一個物件包含了資料和操作資料的函式,
面向程序的程式設計把計算機程式視為一系列的命令集合,即一組函式的順序執行,為了簡化程式設計,面向程序把函式繼續切分為子函式,即把大塊函式通過切割成小塊函式來降低系統的復雜度,
而面向物件的程式設計把計算機程式視為一組物件的集合,而每個物件都可以接收其他物件發過來的訊息,并處理這些訊息,計算機程式的執行就是一系列訊息在各個物件之間傳遞,
在Python中,所有資料型別都可以視為物件,當然也可以自定義物件,自定義的物件資料型別就是面向物件中的類(Class)的概念,
12.1 類和物件
面向物件最重要的概念就是類(Class)和實體(Instance),必須牢記類是抽象的模板,比如Student類,而實體是根據類創建出來的一個個具體的“物件”,每個物件都擁有相同的方法,但各自的資料可能不同,
12.1.1 類
人以類聚 物以群分,
具有相似內部狀態和運動規律的物體的集合(或統稱為抽象),
具有相同屬性和行為事物的統稱
類是抽象的,在使用的時候通常會找到這個類的一個具體的存在,使用這個具體的存在,一個類可以找到多個物件
12.2.2 物件
某一個具體事物的存在 ,在現實世界中可以是看得見摸得著的,
可以是直接使用的
12.2.3 類和物件的關系
類是創建實體的模板,而實體則是一個一個具體的物件,各個實體擁有的資料都互相獨立,互不影響;
12.2.4 定義類
定義一個類,格式如下:
class 類名:
方法串列
例:定義一個Car類
# 定義類
class Car:
# 方法
def getCarInfo(self):
print('車輪子個數:%d, 顏色%s'%(self.wheelNum, self.color))
def move(self):
print("車正在移動...")
說明:
- 定義類時有2種:新式類和經典類,上面的Car為經典類,如果是Car(object)則為新式類
- 類名 的命名規則按照"大駝峰"
12.2.5 創建物件
通過上一節,定義了一個Car類;就好比有車一個張圖紙,那么接下來就應該把圖紙交給生成工人們去生成了
python中,可以根據已經定義的類去創建出一個個物件
創建物件的格式為:
物件名 = 類名()
創建物件demo:
# 定義類
class Car:
# 移動
def move(self):
print('車在奔跑...')
# 鳴笛
def toot(self):
print("車在鳴笛...嘟嘟..")
# 創建一個物件,并用變數BMW來保存它的參考
BMW = Car()
BMW.color = '黑色'
BMW.wheelNum = 4 #輪子數量
BMW.move()
BMW.toot()
print(BMW.color)
print(BMW.wheelNum)
運行結果:
車在奔跑...
車在鳴笛...嘟嘟..
黑色
4
12.2.6 __init__()方法
1)使用方式
def 類名:
#初始化函式,用來完成一些默認的設定
def __init__():
pass
2)__init__()方法的呼叫
# 定義汽車類
class Car:
def __init__(self):
self.wheelNum = 4
self.color = '藍色'
def move(self):
print('車在跑,目標:夏威夷')
# 創建物件
BMW = Car()
print('車的顏色為:%s'%BMW.color)
print('車輪胎數量為:%d'%BMW.wheelNum)
運行結果:
車的顏色為:藍色
車輪胎數量為:4
12.2.7 魔法方法
1)列印id()
如果把BMW使用print進行輸出的話,會看到如下的資訊,例:
# 定義汽車類
class Car:
def __init__(self):
self.wheelNum = 4
self.color = '藍色'
def move(self):
print('車在跑,目標:夏威夷')
# 創建物件
BMW = Car()
print(BMW)
運行結果:
<__main__.Car object at 0x0000014F596F8400>
即看到的是創建出來的BMW物件在記憶體中的地址
2) 定義__str__()方法
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def __str__(self):
msg = "嘿,,,我的顏色是" + self.color + "我有" + str(self.wheelNum) + "個輪胎..."
return msg
def move(self):
print('車在跑,目標:夏威夷')
BMW = Car(4, "白色")
print(BMW)
運行結果:
嘿,,,我的顏色是白色我有4個輪胎...
3)定義__del__()方法
創建物件后,python解釋器默認呼叫__init__()方法;
當洗掉一個物件時,python解釋器也會默認呼叫一個方法,這個方法為__del__()方法
import time
class Animal(object):
# 初始化方法
# 創建完物件后會自動被呼叫
def __init__(self, name):
print('__init__方法被呼叫')
self.__name = name
# 析構方法
# 當物件被洗掉時,會自動被呼叫
def __del__(self):
print("__del__方法被呼叫")
print("%s物件馬上被干掉了..." % self.__name)
# 創建物件
dog = Animal("哈皮狗")
# 洗掉物件
del dog
cat = Animal("波斯貓")
cat2 = cat
cat3 = cat
print("---馬上 洗掉cat物件")
del cat
print("---馬上 洗掉cat2物件")
del cat2
print("---馬上 洗掉cat3物件")
del cat3
print("程式2秒鐘后結束")
time.sleep(2)
運行結果:
__init__方法被呼叫
__del__方法被呼叫
哈皮狗物件馬上被干掉了...
__init__方法被呼叫
---馬上 洗掉cat物件
---馬上 洗掉cat2物件
---馬上 洗掉cat3物件
__del__方法被呼叫
波斯貓物件馬上被干掉了...
程式2秒鐘后結束
- 當有1個變數保存了物件的參考時,此物件的參考計數就會加1
- 當使用del洗掉變數指向的物件時,如果物件的參考計數不會1,比如3,那么此時只會讓這個參考計數減1,即變為2,當再次呼叫del時,變為1,如果再呼叫1次del,此時會真的把物件進行洗掉
總結
- 在python中方法名如果是
__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法 - 當使用print輸出物件的時候,只要自己定義了
__str__(self)方法,那么就會列印從在這個方法中return的資料
常用的魔法方法串列
| 魔法方法 | 含義 |
|---|---|
| 基本的魔法方法 | |
| _new_(cls[, …]) | 1. new 是在一個物件實體化的時候所呼叫的第一個方法 2. 它的第一個引數是這個類,其他的引數是用來直接傳遞給 init 方法 3. new 決定是否要使用該 init 方法,因為 new 可以呼叫其他類的構造方法或者直接回傳別的實體物件來作為本類的實體,如果 new 沒有回傳實體物件,則 init 不會被呼叫 4. new 主要是用于繼承一個不可變的型別比如一個 tuple 或者 string |
| _init_(self[, …]) | 構造器,當一個實體被創建的時候呼叫的初始化方法 |
| _del_(self) | 析構器,當一個實體被銷毀的時候呼叫的方法 |
| _call_(self[, args…]) | 允許一個類的實體像函式一樣被呼叫:x(a, b) 呼叫 x.call(a, b) |
| _len_(self) | 定義當被 len() 呼叫時的行為 |
| _repr_(self) | 定義當被 repr() 呼叫時的行為 |
| _str_(self) | 定義當被 str() 呼叫時的行為 |
| _bytes_(self) | 定義當被 bytes() 呼叫時的行為 |
| _hash_(self) | 定義當被 hash() 呼叫時的行為 |
| _bool_(self) | 定義當被 bool() 呼叫時的行為,應該回傳 True 或 False |
| _format_(self, format_spec) | 定義當被 format() 呼叫時的行為 |
| 有關屬性 | |
| _getattr_(self, name) | 定義當用戶試圖獲取一個不存在的屬性時的行為 |
| _getattribute_(self, name) | 定義當該類的屬性被訪問時的行為 |
| _setattr_(self, name, value) | 定義當一個屬性被設定時的行為 |
| _delattr_(self, name) | 定義當一個屬性被洗掉時的行為 |
| _dir_(self) | 定義當 dir() 被呼叫時的行為 |
| _get_(self, instance, owner) | 定義當描述符的值被取得時的行為 |
| _set_(self, instance, value) | 定義當描述符的值被改變時的行為 |
| _delete_(self, instance) | 定義當描述符的值被洗掉時的行為 |
| 比較運算子 | |
| _lt_(self, other) | 定義小于號的行為:x < y 呼叫 x.lt(y) |
| _le_(self, other) | 定義小于等于號的行為:x <= y 呼叫 x.le(y) |
| _eq_(self, other) | 定義等于號的行為:x == y 呼叫 x.eq(y) |
| _ne_(self, other) | 定義不等號的行為:x != y 呼叫 x.ne(y) |
| _gt_(self, other) | 定義大于號的行為:x > y 呼叫 x.gt(y) |
| _ge_(self, other) | 定義大于等于號的行為:x >= y 呼叫 x.ge(y) |
| 算數運算子 | |
| _add_(self, other) | 定義加法的行為:+ |
| _sub_(self, other) | 定義減法的行為:- |
| _mul_(self, other) | 定義乘法的行為:* |
| _truediv_(self, other) | 定義真除法的行為:/ |
| _floordiv_(self, other) | 定義整數除法的行為:// |
| _mod_(self, other) | 定義取模演算法的行為:% |
| _divmod_(self, other) | 定義當被 divmod() 呼叫時的行為 |
| _pow_(self, other[, modulo]) | 定義當被 power() 呼叫或 ** 運算時的行為 |
| _lshift_(self, other) | 定義按位左移位的行為:<< |
| _rshift_(self, other) | 定義按位右移位的行為:>> |
| _and_(self, other) | 定義按位與操作的行為:& |
| _xor_(self, other) | 定義按位異或操作的行為:^ |
| _or_(self, other) | 定義按位或操作的行為:| |
| 反運算 | |
| _radd_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rsub_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rmul_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rtruediv_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rfloordiv_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rmod_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rdivmod_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rpow_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rlshift_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rrshift_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _rxor_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| _ror_(self, other) | (與上方相同,當左運算元不支持相應的操作時被呼叫) |
| 增量賦值運算 | |
| _iadd_(self, other) | 定義賦值加法的行為:+= |
| _isub_(self, other) | 定義賦值減法的行為:-= |
| _imul_(self, other) | 定義賦值乘法的行為:*= |
| _itruediv_(self, other) | 定義賦值真除法的行為:/= |
| _ifloordiv_(self, other) | 定義賦值整數除法的行為://= |
| _imod_(self, other) | 定義賦值取模演算法的行為:%= |
| _ipow_(self, other[, modulo]) | 定義賦值冪運算的行為:**= |
| _ilshift_(self, other) | 定義賦值按位左移位的行為:<<= |
| _irshift_(self, other) | 定義賦值按位右移位的行為:>>= |
| _iand_(self, other) | 定義賦值按位與操作的行為:&= |
| _ixor_(self, other) | 定義賦值按位異或操作的行為:^= |
| _ior_(self, other) | 定義賦值按位或操作的行為:|= |
| 一元運算子 | |
| _neg_(self) | 定義正號的行為:+x |
| _pos_(self) | 定義負號的行為:-x |
| _abs_(self) | 定義當被 abs() 呼叫時的行為 |
| _invert_(self) | 定義按位求反的行為:~x |
| 型別轉換 | |
| _complex_(self) | 定義當被 complex() 呼叫時的行為(需要回傳恰當的值) |
| _int_(self) | 定義當被 int() 呼叫時的行為(需要回傳恰當的值) |
| _float_(self) | 定義當被 float() 呼叫時的行為(需要回傳恰當的值) |
| _round_(self[, n]) | 定義當被 round() 呼叫時的行為(需要回傳恰當的值) |
| _index_(self) | 1. 當物件是被應用在切片運算式中時,實作整形強制轉換 2. 如果你定義了一個可能在切片時用到的定制的數值型,你應該定義 index 3. 如果 index 被定義,則 int 也需要被定義,且回傳相同的值 |
| 背景關系管理(with 陳述句) | |
| _enter_(self) | 1. 定義當使用 with 陳述句時的初始化行為 2. enter 的回傳值被 with 陳述句的目標或者 as 后的名字系結 |
| _exit_(self, exc_type, exc_value, traceback) | 1. 定義當一個代碼塊被執行或者終止后背景關系管理器應該做什么 2. 一般被用來處理例外,清除作業或者做一些代碼塊執行完畢之后的日常作業 |
| 容器型別 | |
| _len_(self) | 定義當被 len() 呼叫時的行為(回傳容器中元素的個數) |
| _getitem_(self, key) | 定義獲取容器中指定元素的行為,相當于 self[key] |
| _setitem_(self, key, value) | 定義設定容器中指定元素的行為,相當于 self[key] = value |
| _delitem_(self, key) | 定義洗掉容器中指定元素的行為,相當于 del self[key] |
| _iter_(self) | 定義當迭代容器中的元素的行為 |
| _reversed_(self) | 定義當被 reversed() 呼叫時的行為 |
| _contains_(self, item) | 定義當使用成員測驗運算子(in 或 not in)時的行為 |
12.2.8 self
self可以理解為自己,類似C#中的this,例:
# 定義一個類
class Animal:
# 方法
def __init__(self, name):
self.name = name
def printName(self):
print('名字為:%s' % self.name)
# 定義一個函式
def myPrint(animal):
animal.printName()
dog1 = Animal('淘淘')
myPrint(dog1)
dog2 = Animal('貝貝')
myPrint(dog2)
運行結果:
名字為:淘淘
名字為:貝貝
總結
所謂的self,可以理解為自己
可以把self當做C++中類里面的this指標一樣理解,就是物件自身的意思
某個物件呼叫其方法時,python解釋器會把這個物件作為第一個引數傳遞給self,所以開發者只需要傳遞后面的引數即可
12.2 屬性
屬性分為類屬性和實體屬性,
類屬性就是屬于類所有,可以直接用類名.屬性名直接呼叫,類的屬性在記憶體中只有一份,實體屬性就是在__init__()方法中初始化的屬性;
實體屬性屬于類的物件所有,可以用物件名.屬性名的形式進行呼叫,但是不能用類名.屬性名進行呼叫 ,因為實體屬性只有在實體創建時,才會初始化創建,
12.2.1 類屬性
類屬性就是類物件所擁有的屬性,它被所有類物件的實體物件所共有,在記憶體中只存在一個副本,這個和C#中類的靜態成員變數有點類似,對于公有的類屬性,在類外可以通過類物件和實體物件訪問,例:
class People(object):
name = 'Tom' #公有的類屬性
__age = 12 #私有的類屬性
p = People()
print(p.name) #正確
print(People.name) #正確
print(p.__age) #錯誤,不能在類外通過實體物件訪問私有的類屬性
print(People.__age) #錯誤,不能在類外通過類物件訪問私有的類屬性
類屬性的訪問:
import time
class Test(object):
name = 'scolia'
a = Test()
print(Test.name) # 通過類進行訪問
print(a.name) # 通過實體進行訪問
運行結果:
scolia
scolia
可以訪問的,但是,試圖修改這個屬性的話:
class Test(object):
name = 'scolia'
a = Test()
Test.name = 'scolia good' # 通過類進行修改
print(Test.name)
print(a.name)
運行結果:
scolia good
scolia good
我們發現兩者都修改成功了,再嘗試通過實體來修改屬性的話:
class Test(object):
name = 'scolia'
a = Test()
a.name = 'scolia good' # 通過實體進行修改
print(Test.name)
print(a.name)
運行結果:
scolia
scolia good
我們發現類的屬性沒有修改,而實體的屬性則修改成功了,這究竟是為什么?
其實這里的情況非常類似于區域作用域和全域作用域,
我在函式內訪問變數時,會先在函式內部查詢有沒有這個變數,如果沒有,就到外層中找,這里的情況是我在實體中訪問一個屬性,但是我實體中沒有,我就試圖去創建我的類中尋找有沒有這個屬性,找到了,就有,沒找到,就拋出例外,而當我試圖用實體去修改一個在類中不可變的屬性的時候,我實際上并沒有修改,而是在我的實體中創建了這個屬性,而當我再次訪問這個屬性的時候,我實體中有,就不用去類中尋找了,如果用一張圖來表示的話:

12.2.2 實體屬性(物件屬性)
實體屬性是在_init_(self)方法定義的屬性,屬于物件的本身,只能通過物件.屬性來訪問,不能用過類.屬性來訪問,例:
class People(object):
address = '山東' #類屬性
def __init__(self):
self.name = 'xiaowang' #實體屬性
self.age = 20 #實體屬性
p = People()
p.age =12 #實體屬性
print(p.address) #正確
print(p.name) #正確
print(p.age) #正確
print(People.address) #正確
print(People.name) #錯誤
print(People.age) #錯誤
12.2.3 私有屬性
如果有一個物件,當需要對其進行修改屬性時,有2種方法
- 物件名.屬性名 = 資料 ---->直接修改
- 物件名.方法名() ---->間接修改
為了更好的保存屬性安全,即不能隨意修改,一般的處理方式為
- 將屬性定義為私有屬性
- 添加一個可以呼叫的方法,供呼叫
class People(object):
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
def setName(self, newName):
if len(newName) >= 5:
self.__name = newName
else:
print("error:名字長度需要大于或者等于5")
xiaoming = People("AI浩")
print(xiaoming.__name)
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 16, in <module>
print(xiaoming.__name)
AttributeError: 'People' object has no attribute '__name'
直接呼叫私有屬性會報錯,我需要定義個方法,呼叫方法
class People(object):
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
def setName(self, newName):
if len(newName) >= 5:
self.__name = newName
else:
print("error:名字長度需要大于或者等于5")
xiaoming = People("張三")
xiaoming.setName("wanger")
print(xiaoming.getName())
xiaoming.setName("lisi")
print(xiaoming.getName())
運行結果:
wanger
error:名字長度需要大于或者等于5
wanger
總結
- 如果需要在類外修改
類屬性,必須通過類物件去參考然后進行修改,如果通過實體物件去參考,會產生一個同名的實體屬性,這種方式修改的是實體屬性,不會影響到類屬性,并且之后如果通過實體物件去參考該名稱的屬性,實體屬性會強制屏蔽掉類屬性,即參考的是實體屬性,除非洗掉了該實體屬性, - Python中沒有像C++中public和private這些關鍵字來區別公有屬性和私有屬性
- 它是以屬性命名方式來區分,如果在屬性名前面加了2個下劃線’__’,則表明該屬性是私有屬性,否則為公有屬性(方法也是一樣,方法名前面加了2個下劃線的話表示該方法是私有的,否則為公有的),
12.3 繼承
在程式中,繼承描述的是事物之間的所屬關系,例如貓和狗都屬于動物,程式中便可以描述為貓和狗繼承自動物;同理,波斯貓和巴厘貓都繼承自貓,而沙皮狗和斑點狗都繼承足夠,如下如所示:

# 定義一個父類,如下:
class Cat(object):
def __init__(self, name, color="白色"):
self.name = name
self.color = color
def run(self):
print("%s--在跑" % self.name)
# 定義一個子類,繼承Cat類如下:
class Bosi(Cat):
def setNewName(self, newName):
self.name = newName
def eat(self):
print("%s--在吃" % self.name)
bs = Bosi("印度貓")
print('bs的名字為:%s' % bs.name)
print('bs的顏色為:%s' % bs.color)
bs.eat()
bs.setNewName('波斯')
bs.run()
運行結果:
bs的名字為:印度貓
bs的顏色為:白色
印度貓--在吃
波斯--在跑
結論:
-
雖然子類沒有定義
__init__方法,但是父類有,所以在子類繼承父類的時候這個方法就被繼承了,所以只要創建Bosi的物件,就默認執行了那個繼承過來的__init__方法 -
子類在繼承的時候,在定義類時,小括號()中為父類的名字
-
父類的屬性、方法,會被繼承給子類
12.3.1 私有屬性和方法的繼承
class Animal(object):
def __init__(self, name='動物', color='白色'):
self.__name = name
self.color = color
def __test(self):
print(self.__name)
print(self.color)
def test(self):
print(self.__name)
print(self.color)
class Dog(Animal):
def dogTest1(self):
# print(self.__name) #不能訪問到父類的私有屬性
print(self.color)
def dogTest2(self):
# self.__test() #不能訪問父類中的私有方法
self.test()
A = Animal()
# print(A.__name) #程式出現例外,不能訪問私有屬性
print(A.color)
# A.__test() #程式出現例外,不能訪問私有方法
A.test()
print("------分割線-----")
D = Dog(name="小花狗", color="黃色")
D.dogTest1()
D.dogTest2()
運行結果:
白色
動物
白色
------分割線-----
黃色
小花狗
黃色
結論:
私有的屬性,不能通過物件直接訪問,但是可以通過方法訪問
私有的方法,不能通過物件直接訪問
私有的屬性、方法,不會被子類繼承,也不能被訪問
一般情況下,私有的屬性、方法都是不對外公布的,往往用來做內部的事情,起到安全的作用
12.3.2 多繼承
Python中多繼承的格式如下:
# 定義一個父類
class A:
def printA(self):
print('----A----')
# 定義一個父類
class B:
def printB(self):
print('----B----')
# 定義一個子類,繼承自A、B
class C(A,B):
def printC(self):
print('----C----')
obj_C = C()
obj_C.printA()
obj_C.printB()
運行結果:
----A----
----B----
結論:
python中是可以多繼承的
父類中的方法、屬性,子類會繼承
如果父類A和父類B中,有一個同名的方法,那么通過子類去呼叫的時候,呼叫哪個?
# coding=utf-8
class base(object):
def test(self):
print('----base test----')
class A(base):
def test(self):
print('----A test----')
# 定義一個父類
class B(base):
def test(self):
print('----B test----')
# 定義一個子類,繼承自A、B
class C(A, B):
pass
obj_C = C()
obj_C.test()
print("搜索順序:",C.__mro__) # 可以查看C類的物件搜索方法時的先后順序
運行結果:
----A test----
搜索順序: (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.base'>, <class 'object'>)
12.3.3 重寫父類方法
所謂重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆寫掉父類中同名的方法
class Cat(object):
def sayHello(self):
print("halou-----1")
class Bosi(Cat):
def sayHello(self):
print("halou-----2")
bosi = Bosi()
bosi.sayHello()
運行結果:
halou-----2
12.3.4 呼叫父類的方法
呼叫父類的__init__方法
#coding=utf-8
class Cat(object):
def __init__(self,name):
self.name = name
self.color = 'yellow'
class Bosi(Cat):
def __init__(self,name):
# 呼叫父類的__init__方法1(python2)
#Cat.__init__(self,name)
# 呼叫父類的__init__方法2
#super(Bosi,self).__init__(name)
# 呼叫父類的__init__方法3
super().__init__(name)
def getName(self):
return self.name
bosi = Bosi('xiaohua')
print(bosi.name)
print(bosi.color)
運行結果:
xiaohua
yellow
呼叫父類的普通方法
# 父類
class Dog:
def bark(self):
print("汪汪叫")
# 子類 繼承
class XiaoTianQuan(Dog):
def fly(self):
print("我會飛")
# 可以重寫父類中的同名方法
def bark(self):
# super().父類方法名 呼叫父類中的方法 (第一種方式)(推薦)
super().bark()
# 父類名.方法(self) 呼叫父類中的方法 (第二種方式,python2.x)(不推薦,父類名修改后,此處也得改)
Dog.bark(self)
# 注意:如果使用子類名呼叫方法,可能會出現遞回呼叫 -- 死回圈!
# XiaoTianQuan.bark(self) # 會產生死回圈
# 針對子類特有的需求,進行擴展
print("神一樣的叫喚...")
xtq = XiaoTianQuan()
xtq.bark()
運行結果:
汪汪叫
汪汪叫
神一樣的叫喚...
12.4 多型
多型的概念是應用于Java和C#這一類強型別語言中,而Python崇尚“鴨子型別”,
所謂多型:定義時的型別和運行時的型別不一樣,此時就成為多型,例:Python “鴨子型別”
class F1(object):
def show(self):
print ('F1.show')
class S1(F1):
def show(self):
print ('S1.show')
class S2(F1):
def show(self):
print ('S2.show')
def Func(obj):
print (obj.show())
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
運行結果:
S1.show
None
S2.show
None
12.5 靜態方法和類方法
12.5.1 類方法
是類物件所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對于類方法,第一個引數必須是類物件,一般以cls作為第一個引數(當然可以用其他名稱的變數作為其第一個引數,但是大部分人都習慣以’cls’作為第一個引數的名字,就最好用’cls’了),能夠通過實體物件和類物件去訪問,
class People(object):
country = 'china'
# 類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls):
return cls.country
p = People()
print(p.getCountry()) # 可以用過實體物件參考
print(People.getCountry()) # 可以通過類物件參考
類方法還有一個用途就是可以對類屬性進行修改:
class People(object):
country = 'china'
# 類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls, country):
cls.country = country
p = People()
print(p.getCountry()) # 可以用過實體物件參考
print(People.getCountry()) # 可以通過類物件參考
p.setCountry('japan')
print(p.getCountry())
print(People.getCountry())
運行結果:
china
china
japan
japan
結果顯示在用類方法對類屬性修改之后,通過類物件和實體物件訪問都發生了改變
12.5.2 靜態方法
需要通過修飾器@staticmethod來進行修飾,靜態方法不需要多定義引數
class People(object):
country = 'china'
@staticmethod
#靜態方法
def getCountry():
return People.country
print People.getCountry()
總結
從類方法和實體方法以及靜態方法的定義形式就可以看出來,類方法的第一個引數是類物件cls,那么通過cls參考的必定是類物件的屬性和方法;而實體方法的第一個引數是實體物件self,那么通過self參考的可能是類屬性、也有可能是實體屬性(這個需要具體分析),不過在存在相同名稱的類屬性和實體屬性的情況下,實體屬性優先級更高,靜態方法中不需要額外定義引數,因此在靜態方法中參考類屬性的話,必須通過類物件來參考
13 例外
當Python檢測到一個錯誤時,解釋器就無法繼續執行了,反而出現了一些錯誤的提示,這就是所謂的"例外",
13.1 捕獲例外
13.1.1 捕獲例外 try…except…
看如下示例:
try:
print('-----test--1---')
open('123.txt','r')
print('-----test--2---')
except IOError:
pass
運行結果:
-----test--1---
說明:
- 此程式看不到任何錯誤,因為用except 捕獲到了IOError例外,并添加了處理的方法
- pass 表示實作了相應的實作,但什么也不做;如果把pass改為print陳述句,那么就會輸出其他資訊
小總結:

- 把可能出現問題的代碼,放在try中
- 把處理例外的代碼,放在except中
13.1.2 except捕獲多個例外
看如下示例:
try:
print (num)
except IOError:
print('產生錯誤了')
運行結果如下:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 2, in <module>
print(num)
NameError: name 'num' is not defined
想一想:
上例程式,已經使用except來捕獲例外了,為什么還會看到錯誤的資訊提示?
答:
except捕獲的錯誤型別是IOError,而此時程式產生的例外為 NameError ,所以except沒有生效
修改后的代碼為:
try:
print (num)
except NameError:
print('產生錯誤了')
運行結果如下:
產生錯誤了
實際開發中,捕獲多個例外的方式,如下:
#coding=utf-8
try:
print('-----test--1---')
open('123.txt','r') # 如果123.txt檔案不存在,那么會產生 IOError 例外
print('-----test--2---')
print(num)# 如果num變數沒有定義,那么會產生 NameError 例外
except (IOError,NameError):
#如果想通過一次except捕獲到多個例外可以用一個元組的方式
# errorMsg里會保存捕獲到的錯誤資訊
print(errorMsg)
運行結果:
-----test--1---
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 4, in <module>
open('123.txt','r') # 如果123.txt檔案不存在,那么會產生 IOError 例外
FileNotFoundError: [Errno 2] No such file or directory: '123.txt'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 12, in <module>
print(errorMsg)
NameError: name 'errorMsg' is not defined
注意:
- 當捕獲多個例外時,可以把要捕獲的例外的名字,放到except 后,并使用元組的方式僅進行存盤
13.1.3 獲取例外的資訊描述


13.1.4捕獲所有例外


13.1.5 else
咱們應該對else并不陌生,在if中,它的作用是當條件不滿足時執行的實行;同樣在try…except…中也是如此,即如果沒有捕獲到例外,那么就執行else中的事情
try:
num = 100
print (num)
except NameError as errorMsg:
print('產生錯誤了:%s'%errorMsg)
else:
print('沒有捕獲到例外,真高興')
運行結果如下:
100
沒有捕獲到例外,真高興
13.1.6 try…finally…
try…finally…陳述句用來表達這樣的情況:
在程式中,如果一個段代碼必須要執行,即無論例外是否產生都要執行,那么此時就需要使用finally, 比如檔案關閉,釋放鎖,把資料庫連接返還給連接池等
demo:
import time
try:
f = open('test.txt')
try:
while True:
content = f.readline()
if len(content) == 0:
break
time.sleep(2)
print(content)
except:
#如果在讀取檔案的程序中,產生了例外,那么就會捕獲到
#比如 按下了 ctrl+c
pass
finally:
f.close()
print('關閉檔案')
except:
print("沒有這個檔案")
說明:
test.txt檔案中每一行資料列印,但是我有意在每列印一行之前用time.sleep方法暫停2秒鐘,這樣做的原因是讓程式運行得慢一些,在程式運行的時候,按Ctrl+c中斷(取消)程式,
我們可以觀察到KeyboardInterrupt例外被觸發,程式退出,但是在程式退出之前,finally從句仍然被執行,把檔案關閉,
13.2 例外的傳遞
13.2.1. try嵌套中
import time
try:
f = open('test.txt')
try:
while True:
content = f.readline()
if len(content) == 0:
break
time.sleep(2)
print(content)
finally:
f.close()
print('關閉檔案')
except:
print("沒有這個檔案")
運行結果:
沒有這個檔案
13.2.2 函式嵌套呼叫中
def test1():
print("----test1-1----")
print(num)
print("----test1-2----")
def test2():
print("----test2-1----")
test1()
print("----test2-2----")
def test3():
try:
print("----test3-1----")
test1()
print("----test3-2----")
except Exception as result:
print("捕獲到了例外,資訊是:%s" % result)
print("----test3-2----")
test3()
print("------華麗的分割線-----")
test2()
運行結果:
----test3-1----
----test1-1----
捕獲到了例外,資訊是:name 'num' is not defined
----test3-2----
------華麗的分割線-----
----test2-1----
----test1-1----
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 26, in <module>
test2()
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 9, in test2
test1()
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 3, in test1
print(num)
NameError: name 'num' is not defined
總結:
- 如果try嵌套,那么如果里面的try沒有捕獲到這個例外,那么外面的try會接收到這個例外,然后進行處理,如果外邊的try依然沒有捕獲到,那么再進行傳遞,,,
- 如果一個例外是在一個函式中產生的,例如函式A---->函式B---->函式C,而例外是在函式C中產生的,那么如果函式C中沒有對這個例外進行處理,那么這個例外會傳遞到函式B中,如果函式B有例外處理那么就會按照函式B的處理方式進行執行;如果函式B也沒有例外處理,那么這個例外會繼續傳遞,以此類推,,,如果所有的函式都沒有處理,那么此時就會進行例外的默認處理,即通常見到的那樣
- 注意觀察上圖中,當呼叫test3函式時,在test1函式內部產生了例外,此例外被傳遞到test3函式中完成了例外處理,而當例外處理完后,并沒有回傳到函式test1中進行執行,而是在函式test3中繼續執行
13.3 拋出自定義的例外
你可以用raise陳述句來引發一個例外,例外/錯誤物件必須有一個名字,且它們應是Error或Exception類的子類
下面是一個引發例外的例子:
class ShortInputException(Exception):
'''自定義的例外類'''
def __init__(self, length, atleast):
#super().__init__()
self.length = length
self.atleast = atleast
def main():
try:
s = input('請輸入 --> ')
if len(s) < 3:
# raise引發一個你定義的例外
raise ShortInputException(len(s), 3)
except ShortInputException as result:#x這個變數被系結到了錯誤的實體
print('ShortInputException: 輸入的長度是 %d,長度至少應是 %d'% (result.length, result.atleast))
else:
print('沒有例外發生.')
main()
運行結果如下:
請輸入 --> 11
ShortInputException: 輸入的長度是 2,長度至少應是 3
注意
-
以上程式中,關于代碼#super().init()的說明
這一行代碼,可以呼叫也可以不呼叫,建議呼叫,因為
__init__方法往往是用來對創建完的物件進行初始化作業,如果在子類中重寫了父類的__init__方法,即意味著父類中的很多初始化作業沒有做,這樣就不保證程式的穩定了,所以在以后的開發中,如果重寫了父類的__init__方法,最好是先呼叫父類的這個方法,然后再添加自己的功能
13.4 例外處理中拋出例外
class Test(object):
def __init__(self, switch):
self.switch = switch #開關
def calc(self, a, b):
try:
return a/b
except Exception as result:
if self.switch:
print("捕獲開啟,已經捕獲到了例外,資訊如下:")
print(result)
else:
#重新拋出這個例外,此時就不會被這個例外處理給捕獲到,從而觸發默認的例外處理
raise
a = Test(True)
a.calc(11,0)
print("----------------------華麗的分割線----------------")
a.switch = False
a.calc(11,0)
運行結果:
捕獲開啟,已經捕獲到了例外,資訊如下:
division by zero
----------------------華麗的分割線----------------
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 21, in <module>
a.calc(11,0)
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 6, in calc
return a/b
ZeroDivisionError: division by zero
14 模塊
14.1 模塊介紹
14.1.1 Python中的模塊
有過C語言編程經驗的朋友都知道在C語言中如果要參考sqrt函式,必須用陳述句#include <math.h>引入math.h這個頭檔案,否則是無法正常進行呼叫的,
那么在Python中,如果要參考一些其他的函式,該怎么處理呢?
在Python中有一個概念叫做模塊(module),這個和C語言中的頭檔案以及Java中的包很類似,比如在Python中要呼叫sqrt函式,必須用import關鍵字引入math這個模塊,下面就來了解一下Python中的模塊,
說的通俗點:模塊就好比是工具包,要想使用這個工具包中的工具(就好比函式),就需要匯入這個模塊
14.1.2 import
在Python中用關鍵字import來引入某個模塊,比如要參考模塊math,就可以在檔案最開始的地方用import math來引入,
形如:
import module1,mudule2...
當解釋器遇到import陳述句,如果模塊在當前的搜索路徑就會被匯入,
在呼叫math模塊中的函式時,必須這樣參考:
模塊名.函式名
-
想一想:
為什么必須加上模塊名呼叫呢?
-
答:
因為可能存在這樣一種情況:在多個模塊中含有相同名稱的函式,此時如果只是通過函式名來呼叫,解釋器無法知道到底要呼叫哪個函式,所以如果像上述這樣引入模塊的時候,呼叫函式必須加上模塊名
import math
#這樣會報錯
print sqrt(2)
#這樣才能正確輸出結果
print math.sqrt(2)
有時候我們只需要用到模塊中的某個函式,只需要引入該函式即可,此時可以用下面方法實作:
from 模塊名 import 函式名1,函式名2....
不僅可以引入函式,還可以引入一些全域變數、類等
-
注意:
- 通過這種方式引入的時候,呼叫函式時只能給出函式名,不能給出模塊名,但是當兩個模塊中含有相同名稱函式的時候,后面一次引入會覆寫前一次引入,也就是說假如模塊A中有函式function( ),在模塊B中也有函式function( ),如果引入A中的function在先、B中的function在后,那么當呼叫function函式的時候,是去執行模塊B中的function函式,
- 如果想一次性引入math中所有的東西,還可以通過from math import *來實作
14.1.3 from…import
Python的from陳述句讓你從模塊中匯入一個指定的部分到當前命名空間中
語法如下:
from modname import name1[, name2[, ... nameN]]
例如,要匯入模塊fib的fibonacci函式,使用如下陳述句:
from fib import fibonacci
注意
- 不會把整個fib模塊匯入到當前的命名空間中,它只會將fib里的fibonacci單個引入
14.1.4 from … import *
把一個模塊的所有內容全都匯入到當前的命名空間也是可行的,只需使用如下宣告:
from modname import *
注意
- 這提供了一個簡單的方法來匯入一個模塊中的所有專案,然而這種宣告不該被過多地使用,
14.1.5 as
In [1]: import time as tt
In [2]: time.sleep(1)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-07a34f5b1e42> in <module>()
----> 1 time.sleep(1)
NameError: name 'time' is not defined
In [3]:
In [3]:
In [3]: tt.sleep(1)
In [4]:
In [4]:
In [4]: from time import sleep as sp
In [5]: sleep(1)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-5-82e5c2913b44> in <module>()
----> 1 sleep(1)
NameError: name 'sleep' is not defined
In [6]:
In [6]:
In [6]: sp(1)
In [7]:
14.1.6 定位模塊
當你匯入一個模塊,Python決議器對模塊位置的搜索順序是:
- 當前目錄
- 如果不在當前目錄,Python則搜索在shell變數PYTHONPATH下的每個目錄,
- 如果都找不到,Python會察看默認路徑,UNIX下,默認路徑一般為/usr/local/lib/python/
- 模塊搜索路徑存盤在system模塊的sys.path變數中,變數里包含當前目錄,PYTHONPATH和由安裝程序決定的默認目錄,
14.2 制作模塊
14.2.1 定義自己的模塊
在Python中,每個Python檔案都可以作為一個模塊,模塊的名字就是檔案的名字,
比如有這樣一個檔案test.py,在test.py中定義了函式add
test.py
def add(a,b):
return a+b
14.2.2 呼叫自己定義的模塊
那么在其他檔案中就可以先import test,然后通過test.add(a,b)來呼叫了,當然也可以通過from test import add來引入
main.py
import test
result = test.add(11,22)
print(result)
14.2.3 測驗模塊
在實際開中,當一個開發人員撰寫完一個模塊后,為了讓模塊能夠在專案中達到想要的效果,這個開發人員會自行在py檔案中添加一些測驗資訊,例如:
test.py
def add(a,b):
return a+b
# 用來進行測驗
ret = add(12,22)
print('int test.py file,,,,12+22=%d'%ret)
如果此時,在其他py檔案中引入了此檔案的話,想想看,測驗的那段代碼是否也會執行呢!
main.py
import test
result = test.add(11,22)
print(result)
運行現象:
int test.py file,,,,12+22=34
33
至此,可發現test.py中的測驗代碼,應該是單獨執行test.py檔案時才應該執行的,不應該是其他的檔案中參考而執行
為了解決這個問題,python在執行一個檔案時有個變數__name__
直接運行此檔案
def add(a, b):
return a + b
# # 用來進行測驗
# ret = add(12,22)
# print('int test.py file,,,,12+22=%d'%ret)
print("in test.py file,__name__ is %s "%__name__)
運行結果:
in test.py file,__name__ is __main__
在其他檔案中import此檔案
in test.py file,__name__ is test
33
總結:
-
可以根據__name__變數的結果能夠判斷出,是直接執行的python腳本還是被引入執行的,從而能夠有選擇性的執行測驗代碼
執行test.py:
def add(a, b):
return a + b
if __name__ == "__main__":
# 用來進行測驗
ret = add(12, 22)
print('int test.py file,,,,12+22=%d' % ret)
print("in test.py file,__name__ is %s " % __name__)
運行結果:
D:\ProgramData\Anaconda3\python.exe C:/Users/WH/Desktop/Python基礎/test.py
int test.py file,,,,12+22=34
in test.py file,__name__ is __main__
執行main.py :
import test
result = test.add(11, 22)
print(result)
運行結果:
33
14.3 模塊中的__all__
14.3.1 沒有__all__
test.py
class Test(object):
def test(self):
print("Test類中的test函式")
def test1():
print("test1函式")
def test2():
print("test2函式")
main.py呼叫
from test import *
a=Test()
print(a.test())
print(test1())
print(test2())
運行結果:
Test類中的test函式
None
test1函式
None
test2函式
None
14.3.2. 模塊中有__all__
__all__=["Test","test1"]
class Test(object):
def test(self):
print("Test類中的test函式")
def test1():
print("test1函式")
def test2():
print("test2函式")
執行main.py
from test import *
a=Test()
print(a.test())
print(test1())
print(test2())
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 6, in <module>
print(test2())
NameError: name 'test2' is not defined
Test類中的test函式
None
test1函式
None
總結
如果一個檔案中有__all__變數,那么也就意味著這不在變數中的元素,不會被from xxx import *時匯入
14.4 python中的包
14.4.1. 引入包
有2個模塊功能有些聯系

所以將其放到同一個檔案夾下

使用import 檔案.模塊 的方式匯入

使用from 檔案夾 import 模塊 的方式匯入

在msg檔案夾下創建__init__.py檔案

在__init__.py檔案中寫入

重新使用from 檔案夾 import 模塊 的方式匯入

總結:
- 包將有聯系的模塊組織在一起,即放到同一個檔案夾下,并且在這個檔案夾創建一個名字為
__init__.py檔案,那么這個檔案夾就稱之為包 - 有效避免模塊名稱沖突問題,讓應用組織結構更加清晰
14.4.2 __init__.py檔案作用
__init__.py 控制著包的匯入行為
__init__.py為空,僅僅是把這個包匯入,不會匯入包中的模塊
__all__在__init__.py檔案中,定義一個__all__變數,它控制著 from 包名 import *時匯入的模塊
14.5 模塊發布
1.mymodule目錄結構體如下:
.
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
2.編輯setup.py檔案
py_modules需指明所需包含的py檔案
from distutils.core import setup
setup(name="AIhao", version="1.0", description="AIhao's module", author="AIhao", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])
3.構建模塊
python setup.py build
構建后目錄結構
.
├── build
│ └── lib.linux-i686-2.7
│ ├── suba
│ │ ├── aa.py
│ │ ├── bb.py
│ │ └── __init__.py
│ └── subb
│ ├── cc.py
│ ├── dd.py
│ └── __init__.py
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
4.生成發布壓縮包
python setup.py sdist
打包后,生成最終發布壓縮包AIhao-1.0.tar.gz , 目錄結構
.
├── build
│ └── lib.linux-i686-2.7
│ ├── suba
│ │ ├── aa.py
│ │ ├── bb.py
│ │ └── __init__.py
│ └── subb
│ ├── cc.py
│ ├── dd.py
│ └── __init__.py
├── dist
│ └── AIhao-1.0.tar.gz
├── MANIFEST
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
14.6 模塊安裝、使用
14.6.1 安裝的方式
- 找到模塊的壓縮包
- 解壓
- 進入檔案夾
- 執行命令
python setup.py install
注意:
- 如果在install的時候,執行目錄安裝,可以使用
python setup.py install --prefix=安裝路徑
14.6.2 模塊的引入
在程式中,使用from import 即可完成對安裝的模塊使用
from 模塊名 import 模塊名或者*
,然后通過test.add(a,b)來呼叫了,當然也可以通過from test import add來引入
main.py
import test
result = test.add(11,22)
print(result)
14.2.3 測驗模塊
在實際開中,當一個開發人員撰寫完一個模塊后,為了讓模塊能夠在專案中達到想要的效果,這個開發人員會自行在py檔案中添加一些測驗資訊,例如:
test.py
def add(a,b):
return a+b
# 用來進行測驗
ret = add(12,22)
print('int test.py file,,,,12+22=%d'%ret)
如果此時,在其他py檔案中引入了此檔案的話,想想看,測驗的那段代碼是否也會執行呢!
main.py
import test
result = test.add(11,22)
print(result)
運行現象:
int test.py file,,,,12+22=34
33
至此,可發現test.py中的測驗代碼,應該是單獨執行test.py檔案時才應該執行的,不應該是其他的檔案中參考而執行
為了解決這個問題,python在執行一個檔案時有個變數__name__
直接運行此檔案
def add(a, b):
return a + b
# # 用來進行測驗
# ret = add(12,22)
# print('int test.py file,,,,12+22=%d'%ret)
print("in test.py file,__name__ is %s "%__name__)
運行結果:
in test.py file,__name__ is __main__
在其他檔案中import此檔案
in test.py file,__name__ is test
33
總結:
-
可以根據__name__變數的結果能夠判斷出,是直接執行的python腳本還是被引入執行的,從而能夠有選擇性的執行測驗代碼
執行test.py:
def add(a, b):
return a + b
if __name__ == "__main__":
# 用來進行測驗
ret = add(12, 22)
print('int test.py file,,,,12+22=%d' % ret)
print("in test.py file,__name__ is %s " % __name__)
運行結果:
D:\ProgramData\Anaconda3\python.exe C:/Users/WH/Desktop/Python基礎/test.py
int test.py file,,,,12+22=34
in test.py file,__name__ is __main__
執行main.py :
import test
result = test.add(11, 22)
print(result)
運行結果:
33
14.3 模塊中的__all__
14.3.1 沒有__all__
test.py
class Test(object):
def test(self):
print("Test類中的test函式")
def test1():
print("test1函式")
def test2():
print("test2函式")
main.py呼叫
from test import *
a=Test()
print(a.test())
print(test1())
print(test2())
運行結果:
Test類中的test函式
None
test1函式
None
test2函式
None
14.3.2. 模塊中有__all__
__all__=["Test","test1"]
class Test(object):
def test(self):
print("Test類中的test函式")
def test1():
print("test1函式")
def test2():
print("test2函式")
執行main.py
from test import *
a=Test()
print(a.test())
print(test1())
print(test2())
運行結果:
Traceback (most recent call last):
File "C:/Users/WH/Desktop/Python基礎/第一個Python程式.py", line 6, in <module>
print(test2())
NameError: name 'test2' is not defined
Test類中的test函式
None
test1函式
None
總結
如果一個檔案中有__all__變數,那么也就意味著這不在變數中的元素,不會被from xxx import *時匯入
14.4 python中的包
14.4.1. 引入包
有2個模塊功能有些聯系
[外鏈圖片轉存中…(img-SLQzBFTR-1630474706485)]
所以將其放到同一個檔案夾下
[外鏈圖片轉存中…(img-PcvSAxTz-1630474706486)]
使用import 檔案.模塊 的方式匯入
[外鏈圖片轉存中…(img-w8G4goMf-1630474706486)]
使用from 檔案夾 import 模塊 的方式匯入
[外鏈圖片轉存中…(img-sruI0KU8-1630474706487)]
在msg檔案夾下創建__init__.py檔案
[外鏈圖片轉存中…(img-303ePJ8i-1630474706487)]
在__init__.py檔案中寫入
[外鏈圖片轉存中…(img-a9ithVil-1630474706488)]
重新使用from 檔案夾 import 模塊 的方式匯入
[外鏈圖片轉存中…(img-6ClhSwqC-1630474706488)]
總結:
- 包將有聯系的模塊組織在一起,即放到同一個檔案夾下,并且在這個檔案夾創建一個名字為
__init__.py檔案,那么這個檔案夾就稱之為包 - 有效避免模塊名稱沖突問題,讓應用組織結構更加清晰
14.4.2 __init__.py檔案作用
__init__.py 控制著包的匯入行為
__init__.py為空,僅僅是把這個包匯入,不會匯入包中的模塊
__all__在__init__.py檔案中,定義一個__all__變數,它控制著 from 包名 import *時匯入的模塊
14.5 模塊發布
1.mymodule目錄結構體如下:
.
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
2.編輯setup.py檔案
py_modules需指明所需包含的py檔案
from distutils.core import setup
setup(name="AIhao", version="1.0", description="AIhao's module", author="AIhao", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])
3.構建模塊
python setup.py build
構建后目錄結構
.
├── build
│ └── lib.linux-i686-2.7
│ ├── suba
│ │ ├── aa.py
│ │ ├── bb.py
│ │ └── __init__.py
│ └── subb
│ ├── cc.py
│ ├── dd.py
│ └── __init__.py
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
4.生成發布壓縮包
python setup.py sdist
打包后,生成最終發布壓縮包AIhao-1.0.tar.gz , 目錄結構
.
├── build
│ └── lib.linux-i686-2.7
│ ├── suba
│ │ ├── aa.py
│ │ ├── bb.py
│ │ └── __init__.py
│ └── subb
│ ├── cc.py
│ ├── dd.py
│ └── __init__.py
├── dist
│ └── AIhao-1.0.tar.gz
├── MANIFEST
├── setup.py
├── suba
│ ├── aa.py
│ ├── bb.py
│ └── __init__.py
└── subb
├── cc.py
├── dd.py
└── __init__.py
14.6 模塊安裝、使用
14.6.1 安裝的方式
- 找到模塊的壓縮包
- 解壓
- 進入檔案夾
- 執行命令
python setup.py install
注意:
- 如果在install的時候,執行目錄安裝,可以使用
python setup.py install --prefix=安裝路徑
14.6.2 模塊的引入
在程式中,使用from import 即可完成對安裝的模塊使用
from 模塊名 import 模塊名或者*
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296804.html
標籤:AI
上一篇:Yolov5-Pytorch版-Windows下訓練自己的資料集,內含voc批量轉yolo方法。(自稱宇宙超級巨詳細步驟)

