Python貌似有點火熱,上手還是比較簡單的谁帕,自己找了個教程也偷偷的學(xué)習一下儡循,扒了一下網(wǎng)上的圖片和數(shù)據(jù),感覺并不是很難呀(不過之前換電腦检激,代碼丟了肴捉,有點可惜腹侣,不過網(wǎng)上教程一抓一大把,隨便看看也能扒一些基礎(chǔ)的圖片了)齿穗,所以就有了這么一篇基礎(chǔ)的學(xué)習筆記作儿,自己記錄一下楷拳,方便自己以后要用的話很快的能夠撿起來酗钞。
編譯型語言
通過編譯器窍霞,統(tǒng)一編譯,一次性執(zhí)行渴丸,最終生成可執(zhí)行文件(相對執(zhí)行更快)
代表語言:C語言
解釋型語言
逐行解釋每一行代碼,逐行編譯缆瓣,逐行執(zhí)行(跨平臺運行能力更強)宜雀,在不同的操作系統(tǒng)上安裝不同的解釋器七兜,相同源代碼使用不同的解釋器進行工作
代表語言:Python
優(yōu)缺點
優(yōu)點
- 簡單言疗,易學(xué)
- 可讀性強
- 開發(fā)速度快
- 面向?qū)ο?/li>
- 免費竟终,開源
- 可擴展性
- 具有豐富的庫
缺點
- 運行速度相對較慢
- 國內(nèi)市場較小
- 中文資料匱乏
設(shè)計哲學(xué)
- 優(yōu)雅(代碼工整)
- 明確
- 簡單
用一種方法象颖,最好是只有一種方法來做一件事情
Python特點
- 完全面向?qū)ο蟮恼Z言(一切皆對象)
- 擁有一個強大的標準庫
- Python社區(qū)提供了大量的第三方模塊
Python3.0沒有考慮向下的兼容
Python解釋器
- CPython -- 官方版本的C語言實現(xiàn)
- Jython -- 可以運行在Java平臺
- IronPython -- .NET和Mono平臺
- PyPy -- Python實現(xiàn)的佩厚,支持JIT即時編譯
Python變量
1.不用事先聲明變量,賦值過程中就包含了變量的聲明和定義的過程
2.用"=" 賦值说订,左邊是變量名抄瓦,右邊是變量值
3.使用前必須先被初始化(先被賦值)
4.可以通過del語句刪除不再使用的變量
標識符
- 區(qū)分大小寫
- 第一個字符必須是字母或者下劃線
- 不能使用關(guān)鍵字
- 以雙劃線開頭或者結(jié)尾的名稱通常有特殊意義,不建議使用
模塊和包名 -> 全小寫克蚂,盡量簡單
函數(shù)名 -> 全小寫闺鲸,多個單詞用下劃線隔開
類名 -> 首字母大小,采用駝峰命名法
常量名 -> 全大寫埃叭,多個單詞使用下劃線隔開
鏈式賦值
使用同一個對象賦值給多個變量 x = y = 123
系列解包賦值
系列數(shù)據(jù)賦值給對應(yīng)相同個數(shù)的變量(個數(shù)必須保持一致)
a,b,c=4,5,6
常量
Python不支持常量摸恍,沒有語法規(guī)則限制改變一個常量的值。只能約定常量的命名規(guī)則赤屋,以及在程序的邏輯上不對常量的值做出修改
數(shù)字
// 整數(shù)除法 7//2 -> 3
** 冪 2**3 -> 8
divmod()函數(shù)同事得到商和余數(shù) :
divmod(13,3) ->(4,1) 返回元組
整數(shù)
int_var = 1
0b或者0B -> 二進制
0o或者0O -> 八進制
0x或者0X -> 十六進制
自動轉(zhuǎn)型立镶,整數(shù)和浮點數(shù)相加 自動轉(zhuǎn)化成浮點數(shù)
Python3中,int可以存儲任意大小的整數(shù),long 被取消
使用int()實現(xiàn)類型轉(zhuǎn)換
1.浮點數(shù)直接舍去小數(shù)部分类早。 int(9.9) -> 9
2.布爾值True轉(zhuǎn)為1媚媒,F(xiàn)alse轉(zhuǎn)為0。 int(True) -> 1
3.字符串符合整數(shù)格式(浮點數(shù)據(jù)格式不行)則轉(zhuǎn)換成對應(yīng)整數(shù)涩僻,否則報錯
時間的表示
1970年1月1日0點開始缭召,以毫秒計算
time.time()獲得當前時刻栈顷,返回的是以秒為單位精度的浮點值
浮點數(shù)
float_var = 1.0
round(value)可以返回四舍五入的值,但不會改變原有值嵌巷,產(chǎn)生新的值
布爾型
True False
字符串型
字符串
字符串是不可變的 沒有字符類型萄凤,單個字符也是字符串
Python3直接使用Unicode,可以表示世界上任何書名語言的字符
ord('蘇') -> 獲取單個字符的Unicode編碼搪哪。chr(65) 獲取Unicode編碼表示的字符
Python允許空字符串的存在靡努,不包含任何字符且長度為0
字符串切片slice操作
str = "I Love Python"
print(str[2:5]) // 輸出第三個到第五個之間的字符,不包括第六個
print(str[:5]) // 輸出0-5之間的字符串 (不包括第六個)
print(str[2:]) // 輸出第3-最后一個的字符串(包括最后一個)
print(str * 2) // 輸出字符串兩次
print(str + " And Java") // 拼接之后輸出
print(str[0:5:2]) // 最后一個代表步長step
print(str[-6]) // 倒數(shù)6個 Python
print(str[::-1]) // 步長為負晓折,從右到左反向提取
字符串搜索
str.isalnum() // 所有字符全是字母或者數(shù)字
str.count("Love") // 指定字符出現(xiàn)的次數(shù)
str.find("L") // 返回首次出現(xiàn)的下標
str.rfind("o") // 反向搜索惑朦,返回首次出現(xiàn)的下標
去除字符串信息
str.strip("*") // 去除首尾指定信息
str.lstrip("*") // 去除字符串首部左邊指定信息
str.rstrip("*") // 去除字符串尾部右邊指定信息
大小寫轉(zhuǎn)換
str.capitalize() // 產(chǎn)生新的字符串,首字母大寫
str.title() // 產(chǎn)生新的字符串,每個單詞首字母大寫
str.upper() // 產(chǎn)生新的字符串 ,所有字符串轉(zhuǎn)換成大寫
str.lower() // 產(chǎn)生新的字符串 ,所有字符串轉(zhuǎn)換成小寫
str.swapcase() // 產(chǎn)生新的字符串 ,所有字母大小寫轉(zhuǎn)換
排版格式
aa = "str"
print(aa.center(10, "*")) ->***str****
print(aa.ljust(10, "*")) ->str*******
print(aa.rjust(10, "*")) ->*******str
format格式化
aa = "名字是:{0}漓概,年齡是:{1}漾月。{0}是個好小伙"
print(aa.format("Steven", 18))
b = "名字是:{name},年齡是:{age}垛耳。{name}是個好小伙"
print(b.format(name="Steven", age=18)) // 名字是:Steven栅屏,年齡是:18飘千。Steven是個好小伙
填充和對齊
填充和對齊一起使用
^堂鲜、<、>分別是居中护奈、左對齊缔莲、右對齊。后面帶寬度
:號后面帶填充的字符霉旗,只能是一個字符痴奏,不指定的話默認是空格填充
a = "我的電話號碼是{0:*^11}"
print(a.format(888)) // 我的電話號碼是****888****
數(shù)字格式化
浮點數(shù)通過f,整數(shù)通過d進行需要的格式化
數(shù)字 格式 輸出 描述
3.1415926 {:.2f} 3.14 保留小數(shù)點后兩位
3.1415926 {:+.2f} 3.14 帶符號保留小數(shù)點后兩位
2.71828 {:.0f} 3 不帶小數(shù)
5 {:0>2d} 05 數(shù)字補零 (填充左邊, 寬度為 2)
5 {:x<4d} 5xxx 數(shù)字補 x (填充右邊, 寬度為 4)
10 {:x<4d} 10xx 數(shù)字補 x (填充右邊, 寬度為 4)
1000000 {:,} 1,000,000 以逗號分隔的數(shù)字格式
0.25 {:.2%} 25.00% 百分比格式
1000000000 {:.2e} 1.00E+09 指數(shù)記法
13 {:10d} 13 右對齊 (默認, 寬度為 10)
13 {:<10d} 13 左對齊 (寬度為 10)
13 {:^10d} 13 中間對齊 (寬度為 10)
字符串拼接
- +兩邊都是字符串,則拼接
- +兩邊都是數(shù)字厌秒,則加法運算
- +兩邊類型不同读拆,則拋異常
不換行打印
print("字符串",end = "*") 打印時不會換行,換行符替換成了*符號鸵闪,使用*連接檐晕。*可以是任意字符串
str()實現(xiàn)數(shù)字轉(zhuǎn)型字符串
replace()會生成一個新的字符串對象
join字符串拼接
"".join(列表) ->使用將列表中的字符串連接起來
可變字符串 io.StringIo(s)
修改過程中不會產(chǎn)生新的字符串對象
列表
類似于Java中的數(shù)組,是一個有序可變的集合容器蚌讼,支持內(nèi)置的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)甚至是列表辟灰,列表是可以嵌套的。不同的數(shù)據(jù)結(jié)構(gòu)可以放在同一個列表中篡石,沒有統(tǒng)一類型的限制
list_a = ["str", 1, 1.0]
元組
不可變的列表芥喇,在賦值之后就不能二次更改了
tuple_a = ("str", 1, ["a", "b", 1], 2.0)
輸出結(jié)果: ('str', 1, ['a', 'b', 1], 2.0)
字典(用的比較多)
類似于Java中的map,key-value鍵值對的形式 無序的容器
dict_a = {
"name": "Steven",
"age": 27,
1: "1800000000"
}
print(dict_a) // {'name': 'Steven', 'age': 27, 1: '1800000000'}
print(dict_a["name"]) // Steven
print(dict_a[1]) // 1800000000
print("name" in dict_a) 判斷是否包含改鍵值// True
print(dict_a.keys()) // dict_keys(['name', 'age', 1])
print(dict_a.values()) // dict_values(['Steven', 27, '1800000000'])
print(dict_a.items()) // dict_items([('name', 'Steven'), ('age', 27), (1, '1800000000')])
邏輯運算符
- and 與關(guān)系 類似于Java中的&& x and y ->x 為true,則返回y的值凰萨。x為false继控,則直接返回false
- or 或關(guān)系 類似于Java中的|| x or y ->x 為true械馆,則直接返回true。x為false武通,則返回y的值
- not 非 類似于Java中的狱杰!
同一運算符is(is not)
用于比較兩個對象的存儲單元,實際比較的是對象的地址
整數(shù)緩存問題
Python僅僅在命令行中執(zhí)行時對較小的整數(shù)對象進行緩存,范圍為[-5,256]之內(nèi)的整數(shù)緩存起來厅须。而在Pycharm或者保存為文件執(zhí)行時仿畸,緩存范圍是[-5,任意正整數(shù)]
if語句
if (a == b):
print("a == b")
else:
print("a != b")
turtle圖形繪制庫
\行連接符 續(xù)行符
變量位于:堆內(nèi)存
對象位于:棧內(nèi)存
序列
序列是一種數(shù)據(jù)存儲方式朗和,用來存儲一系列的數(shù)據(jù)错沽。在內(nèi)存中,序列就是一塊用來存放多個值的連續(xù)的內(nèi)存空間眶拉。
常用的序列結(jié)構(gòu):字符串千埃、列表、元組忆植、字典放可、集合
列表:用于存儲任意數(shù)目、任意類型的數(shù)據(jù)集合朝刊。
列表對象的常用方法匯總?cè)缦?
方法 要點 描述
list.append(x) 增加元素 將元素 x 增加到列表 list 尾部
list.extend(aList) 增加元素 將列表 alist 所有元素加到列表 list 尾部
list.insert(index,x) 增加元素 在列表 list 指定位置 index 處插入元素 x
list.remove(x) 刪除元素 在列表 list 中刪除首次出現(xiàn)的指定元素 x
list.pop([index]) 刪除元素 刪除并返回列表 list 指定位置 index 處的元素耀里,默認是最后一個元素
list.clear() 刪除所有元素 刪除列表所有元素,并不是刪除列表對象
list.index(x) 訪問元素 返回第一個 x 的索引位置拾氓,若不存在 x 元素拋出異常
list.count(x) 計數(shù) 返回指定元素 x 在列表 list 中出現(xiàn)的次數(shù)
len(list) 列表長度 返回列表中包含元素的個數(shù)
list.reverse() 翻轉(zhuǎn)列表 所有元素原地翻轉(zhuǎn)
list.sort() 排序 所有元素原地排序
list.copy() 淺拷貝 返回列表對象的淺拷貝
Python的列表大小可變冯挎,根據(jù)需要隨時增加或縮小
列表的創(chuàng)建
基本語法[ ]創(chuàng)建
a = [10,20,'gaoqi','sxt']
a = [] #創(chuàng)建一個空的列表對象
list()創(chuàng)建
使用 list()可以將任何可迭代的數(shù)據(jù)轉(zhuǎn)化成列表。
a = list() #創(chuàng)建一個空的列表對象
a = list(range(10))
a - > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a = list("gaoqi,sxt")
a - > ['g', 'a', 'o', 'q', 'i', ',', 's', 'x', 't']
range()創(chuàng)建整數(shù)列表
range()可以幫助我們非常方便的創(chuàng)建整數(shù)列表咙鞍,這在開發(fā)中及其有用房官。語法格式為:
range([start,] end [,step])
start 參數(shù):可選,表示起始數(shù)字续滋。默認是 0
end 參數(shù):必選翰守,表示結(jié)尾數(shù)字。
step 參數(shù):可選疲酌,表示步長蜡峰,默認為 1
python3 中 range()返回的是一個 range 對象,而不是列表徐勃。我們需要通過 list()方法將其轉(zhuǎn)換成列表對象
a = [x*2 for x in range(100) if x%9==0] #通過 if 過濾元素
[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
列表元素的增加和刪除
當列表增加和刪除元素時事示,列表會自動進行內(nèi)存管理,大大減少了程序員的負擔僻肖。但這個特點涉及列表元素的大量移動肖爵,效率較低。除非必要臀脏,我們一般只在列表的尾部添加元素或刪除元素劝堪,這會大大提高列表的操作效率冀自。
append()方法
原地修改列表對象,是真正的列表尾部添加新的元素秒啦,速度最快熬粗,推薦使用。
a = [20,40]
a.append(80)
+運算符操作
并不是真正的尾部添加元素余境,而是創(chuàng)建新的列表對象驻呐;將原列表的元素和新列表的元素依次復(fù)制到新的列表對象中。這樣芳来,會涉及大量的復(fù)制操作含末,對于操作大量元素不建議使用。
a = a+[50]
extend()方法
將目標列表的所有元素添加到本列表的尾部即舌,屬于原地操作佣盒,不創(chuàng)建新的列表對象。
a.extend([50,60])
insert()插入元素
使用 insert()方法可以將指定的元素插入到列表對象的任意制定位置顽聂。這樣會讓插入位置后
面所有的元素進行移動肥惭,會影響處理速度。涉及大量元素時紊搪,盡量避免使用蜜葱。
類似發(fā)生這種移動的函數(shù)還有:remove()拨扶、pop()、del()蚣抗,它們在刪除非尾部元素時也會發(fā)生操作位置后面元素的移動寡壮。
a.insert(2,100)
列表元素的刪除
本質(zhì)上是列表的拷貝,將后面的賦值拷貝到前面的值中
del 刪除
del a[1]
pop()方法
pop()刪除并返回指定位置元素寒瓦,如果未指定位置則默認操作列表最后一個元素。
a = [10, 20, 30, 40]
a.pop() -> 返回 40
a.pop(1) -> 返回 20
remove()方法
刪除首次出現(xiàn)的指定元素,若不存在該元素拋出異常诗良。
a = [10,20,30,40,50,20,30,20,30]
a.remove(20)
列表元素訪問和計數(shù)
通過索引直接訪問元素
我們可以通過索引直接訪問元素。索引的區(qū)間在[0, 列表長度-1]這個范圍鲁驶。超過這個范圍則會拋出異常鉴裹。
index()獲得指定元素在列表中首次出現(xiàn)的索引
index()可以獲取指定元素首次出現(xiàn)的索引位置。語法是:index(value,[start,[end]])钥弯。其中径荔,
start 和 end 指定了搜索的范圍。
count()獲得指定元素在列表中出現(xiàn)的次數(shù)
len()返回列表長度
成員資格判斷
判斷列表中是否存在指定的元素脆霎,我們可以使用 count()方法总处,返回 0 則表示不存在,返回大于 0 則表示存在睛蛛。但是鹦马,一般我們會使用更加簡潔的 in 關(guān)鍵字來判斷胧谈,直接返回 True或 False。
切片操作
切片是 Python 序列及其重要的操作荸频,適用于列表菱肖、元組、字符串等等
切片 slice 操作可以讓我們快速提取子列表或修改旭从。標準格式為:
[起始偏移量 start:終止偏移量 end[:步長 step]]
操作和說明 示例 結(jié)果
[:] 提取整個列表 [10,20,30][:] [10,20,30]
[start:]從 start 索引開始到結(jié)尾 [10,20,30][1:] [20,30]
[:end]從頭開始直到 end-1 [10,20,30][:2] [10,20]
[start:end]從start到 end-1 [10,20,30,40][1:3] [20,30]
[start:end:step] 從 start 提取到 end-1稳强,步長是 step [10,20,30,40,50,60,70][1:6:2] [20, 40, 60]
其他操作(三個量為負數(shù))的情況:
示例 說明 結(jié)果
[10,20,30,40,50,60,70][-3:] 倒數(shù)三個 [50,60,70]
10,20,30,40,50,60,70][-5:-3] 倒數(shù)第五個到倒數(shù)第三個(包頭不包尾) [30,40]
[10,20,30,40,50,60,70][::-1] 步長為負,從右到左反向提取 [70, 60, 50, 40, 30, 20, 10]
切片操作時和悦,起始偏移量和終止偏移量不在[0,字符串長度-1]這個范圍键袱,也不會報錯。起始
偏移量小于 0 則會當做 0摹闽,終止偏移量大于“長度-1”會被當成”長度-1”
列表的遍歷
for obj in listObj:
print(obj)
列表排序
修改原列表蹄咖,不建新列表的排序
a.sort() #默認是升序排列
a.sort(reverse=True) #降序排列
random.shuffle(a) #打亂順序
建新列表的排序
通過內(nèi)置函數(shù) sorted()進行排序,這個方法返回新列表付鹿,不對原列表做修改澜汤。
a = sorted(a) #默認升序
c = sorted(a,reverse=True) #降序
reversed()返回迭代器
內(nèi)置函數(shù) reversed()也支持進行逆序排列,與列表對象 reverse()方法不同的是舵匾,內(nèi)置函數(shù)
reversed()不對原列表做任何修改俊抵,只是返回一個逆序排列的迭代器對象。
迭代器只能使用一次 第二次會返回空
a = [20,10,30,40]
c = reversed(a)
max 和 min
用于返回列表中最大和最小值坐梯。
max(a)
min(a)
sum
對數(shù)值型列表的所有元素進行求和操作徽诲,對非數(shù)值型列表運算則會報錯。
sum(a)
多維列表
二維列表
一維列表可以幫助我們存儲一維吵血、線性的數(shù)據(jù)谎替。
二維列表可以幫助我們存儲二維、表格的數(shù)據(jù)蹋辅。
a = [
["高小一",18,30000,"北京"],
["高小二",19,20000,"上海"],
["高小一",20,10000,"深圳"],
]
print(a[1][0],a[1][1],a[1][2])
元組 tuple
列表屬于可變序列钱贯,可以任意修改列表中的元素。元組屬于不可變序列侦另,不能修改元組中的元素秩命。因此,元組沒有增加元素褒傅、修改元素弃锐、刪除元素相關(guān)的方法。
元組支持如下操作:
1. 索引訪問
2. 切片操作
3. 連接操作
4. 成員關(guān)系操作
5. 比較運算操作
6. 計數(shù):元組長度 len()殿托、最大值 max()霹菊、最小值 min()、求和 sum()等碌尔。
-
通過()創(chuàng)建元組浇辜。小括號可以省略券敌。
a = (10,20,30) 或者 a = 10,20,30
如果元組只有一個元素,則必須后面加逗號柳洋。這是因為解釋器會把(1)解釋為整數(shù) 1待诅,(1,)解釋為元組。
-
通過 tuple()創(chuàng)建元組
tuple(可迭代的對象)b = tuple() #創(chuàng)建一個空元組對象 b = tuple("abc") b = tuple(range(3)) b = tuple([2,3,4])
tuple()可以接收列表熊镣、字符串卑雁、其他序列類型、迭代器等生成元組绪囱。
list()可以接收元組测蹲、字符串、其他序列類型鬼吵、迭代器等生成列表扣甲。
元組的元素訪問和計數(shù)
元組的元素不能修改
-
元組的元素訪問和列表一樣,只不過返回的仍然是元組對象齿椅。
a = (20,10,30,9,8) a[1] -> 10 a[1:3] -> (10, 30) a[:4] -> (20, 10, 30, 9)
-
列表關(guān)于排序的方法 list.sort()是修改原列表對象琉挖,元組沒有該方法。如果要對元組排序涣脚,只能使用內(nèi)置函數(shù) sorted(tupleObj)示辈,并生成新的列表對象。
a = (20,10,30,9,8) sorted(a) -> [8, 9, 10, 20, 30]
zip
zip(列表 1遣蚀,列表 2矾麻,...)將多個列表對應(yīng)位置的元素組合成為元組,并返回這個 zip 對象
a = [10,20,30]
b = [40,50,60]
c = [70,80,90]
d = zip(a,b,c)
list(d) -> [(10, 40, 70), (20, 50, 80), (30, 60, 90)]
生成器推導(dǎo)式創(chuàng)建元組
從形式上看芭梯,生成器推導(dǎo)式與列表推導(dǎo)式類似险耀,只是生成器推導(dǎo)式使用小括號。列表推
導(dǎo)式直接生成列表對象粥帚,生成器推導(dǎo)式生成的不是列表也不是元組胰耗,而是一個生成器對象。
我們可以通過生成器對象芒涡,轉(zhuǎn)化成列表或者元組。也可以使用生成器對象的__next__()
方法進行遍歷卖漫,或者直接作為迭代器對象來使用费尽。不管什么方式使用,元素訪問結(jié)束后羊始,如果需要重新訪問其中的元素旱幼,必須重新創(chuàng)建該生成器對象。
s = (x * 2 for x in range(5))
print(tuple(s)) -> (0, 2, 4, 6, 8) #只能訪問一次元素突委。第二次就為空了柏卤。需要再生成一次
元組總結(jié)
- 元組的核心特點是:不可變序列冬三。
- 元組的訪問和處理速度比列表快。
- 與整數(shù)和字符串一樣缘缚,元組可以作為字典的鍵勾笆,列表則永遠不能作為字典的鍵使用。
字典
字典是“鍵值對”的無序可變序列桥滨,字典中的每個元素都是一個“鍵值對”窝爪,包含:“鍵
對象”和“值對象”∑朊剑可以通過“鍵對象”實現(xiàn)快速獲取蒲每、刪除、更新對應(yīng)的“值對象”喻括。
鍵”是任意的不可變數(shù)據(jù)邀杏,比如:整數(shù)、浮點數(shù)唬血、字符串淮阐、元組。但是:列表刁品、
字典泣特、集合這些可變對象,不能作為“鍵”挑随。并且“鍵”不可重復(fù)状您。
字典的創(chuàng)建
-
我們可以通過{}、dict()來創(chuàng)建字典對象兜挨。
a = {'name':'Steven','age':18,'job':'programmer'} b = dict(name='Steven',age=18,job='programmer') a = dict([("name","Steven"),("age",18)]) a = dict({("name", "Steven"), ("age", 18)}) a = dict({'name': 'Steven', 'age': 18, 'job': 'programmer'}) c = {} #空的字典對象 d = dict() #空的字典對象
-
通過 zip()創(chuàng)建字典對象
k = ['name','age','job'] v = ['Steven',18,'programmer'] d = dict(zip(k,v)) print(d) -> {'name': 'Steven', 'age': 18, 'job':'programmer'}
-
通過 fromkeys 創(chuàng)建值為空的字典
a = dict.fromkeys(['name','age','job']) print(a) -> {'name': None, 'age': None, 'job': None} # none 是一個值膏孟,表示沒有賦值
字典元素的訪問
a = {'name':'Steven','age':18,'job':'programmer'}
-
通過 [鍵] 獲得“值”。若鍵不存在拌汇,則拋出異常柒桑。
a['name'] -> 'Steven'
-
通過 get()方法獲得“值”。推薦使用噪舀。優(yōu)點是:指定鍵不存在魁淳,返回 None;也可以設(shè)定指定鍵不存在時默認返回的對象与倡。推薦使用 get()獲取“值對象”界逛。
a.get('name') -> 'Steven' a.get('sex','一個男人') -> '一個男人'
-
列出所有的鍵值對
a.items() -> dict_items([('name', 'Steven'), ('age', 18), ('job', 'programmer')])
-
列出所有的鍵,列出所有的值
a.keys() -> dict_keys(['name', 'age', 'job']) a.values() -> dict_values(['Steven', 18, 'programmer'])
-
len() 鍵值對的個數(shù)
len(a) a.__len__()
-
檢測一個“鍵”是否在字典中
print("name" in a) -> True
字典元素添加纺座、修改息拜、刪除
-
給字典新增“鍵值對”。如果“鍵”已經(jīng)存在,則覆蓋舊的鍵值對少欺;如果“鍵”不存在喳瓣,
則新增“鍵值對”。a['address']='世界大廈1101' a['age']=16 print(a) -> {'name': 'Steven', 'age': 16, 'job': 'programmer', 'address': '世界大廈1101'}
-
使用 update()將新字典中所有鍵值對全部添加到舊字典對象上赞别。如果 key 有重復(fù)畏陕,則直接覆蓋
b = {'name': 'StevenSon', 'money': 1000, 'sex': '男的'} a.update(b) print(a) -> {'name': 'StevenSon', 'age': 16, 'job': 'programmer', 'money': 1000, 'sex': '男的'}
-
字典中元素的刪除,可以使用 del()方法氯庆;或者 clear()刪除所有鍵值對蹭秋;pop()刪除指定鍵值對,并返回對應(yīng)的“值對象”堤撵;
del(a["name"]) print(a) -> {'age': 18, 'job': 'programmer'} a_value = a.pop("age") print(a) -> {'job': 'programmer'} print(a_value) -> 18
-
popitem() :隨機刪除和返回該鍵值對仁讨。若想一個接一個地移除并處理項,這個方法就非常有效(因為不用首先獲取鍵的列表)实昨。
print(a.popitem()) -> ('job', 'programmer') print(a) -> {'name': 'Steven', 'age': 18}
序列解包
序列解包可以用于元組洞豁、列表、字典荒给。序列解包可以讓我們方便的對多個變量賦值丈挟。
x,y,z=(20,30,10)
(a,b,c)=(9,8,10)
[a,b,c]=[10,20,30]
序列解包用于字典時,默認是對“鍵”進行操作志电; 如果需要對鍵值對操作曙咽,則需要使用
items();如果需要對“值”進行操作挑辆,則需要使用 values()例朱;
s = {'name':'gaoqi','age':18,'job':'teacher'}
name,age,job=s #默認對鍵進行操作
name,age,job=s.items() #對鍵值對進行操作
name,age,job=s.values() #對值進行操作
字典核心底層原理(重要)
字典對象的核心是散列表。散列表是一個稀疏數(shù)組(總是有空白元素的數(shù)組)鱼蝉,數(shù)組的
每個單元叫做 bucket洒嗤。每個 bucket 有兩部分:一個是鍵對象的引用,一個是值對象的引用魁亦。
由于渔隶,所有 bucket 結(jié)構(gòu)和大小一致,我們可以通過偏移量來讀取指定 bucket洁奈。
根據(jù)鍵查找“鍵值對”的底層過程
用法總結(jié):
-
鍵必須可散列
(1) 數(shù)字间唉、字符串、元組睬魂,都是可散列的终吼。
(2) 自定義對象需要支持下面三點:1 支持 hash()函數(shù) 2 支持通過__eq__()方法檢測相等性。 3 若 a==b 為真氯哮,則 hash(a)==hash(b)也為真。
字典在內(nèi)存中開銷巨大,典型的空間換時間喉钢。
鍵查詢速度很快
往字典里面添加新建可能導(dǎo)致擴容姆打,導(dǎo)致散列表中鍵的次序變化。因此肠虽,不要在遍歷字典的同時進行字典的修改幔戏。 會報RuntimeError: dictionary changed size during iteration錯誤
集合
集合是無序可變,元素不能重復(fù)税课。實際上闲延,集合底層是字典實現(xiàn),集合的所有元素都是字典中的“鍵對象”韩玩,因此是不能重復(fù)的且唯一的垒玲。
集合創(chuàng)建和刪除
-
使用{}創(chuàng)建集合對象,并使用 add()方法添加元素
a = {3, 5, 7} a.add(9)
-
使用 set()找颓,將列表合愈、元組等可迭代對象轉(zhuǎn)成集合。如果原來數(shù)據(jù)存在重復(fù)數(shù)據(jù)击狮,則只保留一個佛析。
b = set(a)
-
remove()刪除指定元素;clear()清空整個集合
a.remove(3)
集合相關(guān)操作
Python 對集合提供了并集彪蓬、交集寸莫、差集等運算
a = {1, 3, 'sxt'}
b = {'he', 'it', 'sxt'}
a|b 或者 a.union(b) #并集 -> {1, 3, 'sxt', 'he', 'it'}
a&b 或者 a.intersection(b) #交集 ->{'sxt'}
a-b 或者 a.difference(b) #差集 ->{1, 3}
控制語句
選擇結(jié)構(gòu)
單分支選擇結(jié)構(gòu)
if 語句單分支結(jié)構(gòu)的語法形式如下:
if 條件表達式:
語句/語句塊
num = input("輸入一個數(shù)字:")
if int(num)<10:
print(num)
條件表達式詳解
在選擇和循環(huán)結(jié)構(gòu)中,條件表達式的值為 False 的情況如下:
False档冬、0膘茎、0.0、空值 None捣郊、空序列對象(空列表辽狈、空元祖、空集合呛牲、空字典刮萌、空字符串)、空 range 對象娘扩、空迭代對象着茸。其他情況均為True
條件表達式中,不能有賦值操作符“=”
雙分支選擇結(jié)構(gòu)
雙分支結(jié)構(gòu)的語法格式如下:
if 條件表達式 :
語句 1/語句塊 1
else:
語句 2/語句塊 2
三元條件運算符
Python 提供了三元運算符琐旁,用來在某些簡單雙分支賦值情況涮阔。三元條件運算符語法格式如下:
條件為真時的值 if (條件表達式) else 條件為假時的值
多分支選擇結(jié)構(gòu)
多分支選擇結(jié)構(gòu)的語法格式如下:
if 條件表達式 1 :
語句 1/語句塊 1
elif 條件表達式 2:
語句 2/語句塊 2
.
.
.
elif 條件表達式 n :
語句 n/語句塊 n
[else:
語句 n+1/語句塊 n+1
]
【注】計算機行業(yè),描述語法格式時灰殴,使用中括號[ ]通常表示可選敬特,非必選。
選擇結(jié)構(gòu)嵌套
選擇結(jié)構(gòu)可以嵌套,使用時一定要注意控制好不同級別代碼塊的縮進量伟阔,因為縮進量決定了代碼的從屬關(guān)系辣之。
循環(huán)結(jié)構(gòu)
循環(huán)結(jié)構(gòu)用來重復(fù)執(zhí)行一條或多條語句。表達這樣的邏輯:如果符合條件皱炉,則反復(fù)執(zhí)行循環(huán)體里的語句怀估。在每次執(zhí)行完后都會判斷一次條件是否為 True,如果為 True 則重復(fù)執(zhí)行循環(huán)體里的語句合搅。
循環(huán)體里面的語句至少應(yīng)該包含改變條件表達式的語句多搀,以使循環(huán)趨于結(jié)束;否則灾部,就會變成一個死循環(huán)康铭。
while 循環(huán)
while 循環(huán)的語法格式如下:
while 條件表達式:
循環(huán)體語句
for 循環(huán)和可迭代對象遍歷
for 循環(huán)通常用于可迭代對象的遍歷。for 循環(huán)的語法格式如下:
for 變量 in 可迭代對象:
循環(huán)體語句
可迭代對象
Python 包含以下幾種可迭代對象:
- 序列梳猪。包含:字符串麻削、列表、元組
- 字典
- 迭代器對象(iterator)
- 生成器函數(shù)(generator)
- 文件對象
range 對象
range 對象是一個迭代器對象春弥,用來產(chǎn)生指定范圍的數(shù)字序列呛哟。格式為:
range(start, end [,step])
生成的數(shù)值序列從 start 開始到 end 結(jié)束(不包含 end)。若沒有填寫 start匿沛,則默認從 0開始扫责。step 是可選的步長,默認為 1逃呼。
for i in range(10) 產(chǎn)生序列:0 1 2 3 4 5 6 7 8 9
for i in range(3,10) 產(chǎn)生序列:3 4 5 6 7 8 9
for i in range(3,10,2) 產(chǎn)生序列:3 5 7 9
break 語句
break 語句可用于 while 和 for 循環(huán)鳖孤,用來結(jié)束整個循環(huán)。當有嵌套循環(huán)時抡笼,break 語句只能跳出最近一層的循環(huán)苏揣。
continue 語句
continue 語句用于結(jié)束本次循環(huán),繼續(xù)下一次推姻。多個循環(huán)嵌套時平匈,continue 也是應(yīng)用于最
近的一層循環(huán)。
else 語句
while藏古、for 循環(huán)可以附帶一個 else 語句(可選)增炭。如果 for、while 語句沒有被 break 語句
結(jié)束拧晕,則會執(zhí)行 else 子句隙姿,否則不執(zhí)行。語法格式如下:
while 條件表達式:
循環(huán)體
else:
語句塊
或者:
for 變量 in 可迭代對象:
循環(huán)體
else:
語句塊
循環(huán)代碼優(yōu)化
編寫循環(huán)時厂捞,遵守下面三個原則可以大大提高運行效率输玷,避免不必要的低效計算:
- 盡量減少循環(huán)內(nèi)部不必要的計算
- 嵌套循環(huán)中队丝,盡量減少內(nèi)層循環(huán)的計算,盡可能向外提饲嗽。
- 局部變量查詢較快炭玫,盡量使用局部變量
其他優(yōu)化手段
- 連接多個字符串奈嘿,使用 join()而不使用+
- 列表進行元素插入和刪除貌虾,盡量在列表尾部操作
使用 zip()并行迭代
我們可以通過 zip()函數(shù)對多個序列進行并行迭代,zip()函數(shù)在最短序列“用完”時就會停止裙犹。
names = ("Steven","高老二","高老三","高老四")
ages = (18,16,20,25)
jobs = ("老師","程序員","公務(wù)員")
for name,age,job in zip(names,ages,jobs):
print("{0}--{1}--{2}".format(name,age,job)
執(zhí)行結(jié)果:
Steven--18--老師
高老二--16--程序員
高老三--20--公務(wù)員
推導(dǎo)式創(chuàng)建序列
推導(dǎo)式是從一個或者多個迭代器快速創(chuàng)建序列的一種方法尽狠。它可以將循環(huán)和條件判斷結(jié)合,
從而避免冗長的代碼叶圃。推導(dǎo)式是典型的 Python 風格袄膏,會使用它代表你已經(jīng)超過 Python 初
學(xué)者的水平。
列表推導(dǎo)式
列表推導(dǎo)式生成列表對象掺冠,語法如下:
[表達式 for item in 可迭代對象 ]
或者:
{表達式 for item in 可迭代對象 if 條件判斷
[x*2 for x in range(1,5)] -> [2, 4, 6, 8]
[x*2 for x in range(1,20) if x5==0 ] -> [10, 20, 30]
[a for a in "abcdefg"] -> ['a', 'b', 'c', 'd', 'e', 'f', 'g']
cells = [(row,col) for row in range(1,10) for col in range(1,10)] #可以使用兩個循環(huán)
字典推導(dǎo)式
字典的推導(dǎo)式生成字典對象沉馆,格式如下:
{key_expression : value_expression for 表達式 in 可迭代對象}
my_text = ' i love you, i love sxt,i love Steven'
char_count = {c:my_text.count(c) for c in my_text}
集合推導(dǎo)式
集合推導(dǎo)式生成集合,和列表推導(dǎo)式的語法格式類似:
{表達式 for item in 可迭代對象 }
或者:
{表達式 for item in 可迭代對象 if 條件判斷}
生成器推導(dǎo)式(生成元組)
元組是沒有推導(dǎo)式的,推導(dǎo)式推導(dǎo)出的是一個生成器德崭,可以通過生成器生成元組斥黑。一個生成器只能運行一次。第一次迭代可以得到數(shù)據(jù)眉厨,第二次迭代發(fā)現(xiàn)數(shù)據(jù)已經(jīng)沒有了锌奴。
tunple((x for x in range(4))) -> (0, 1, 2, 3)
函數(shù)用法和底層分析
Python 函數(shù)的分類
Python 中函數(shù)分為如下幾類:
- 內(nèi)置函數(shù)
我們前面使用的 str()、list()憾股、len()等這些都是內(nèi)置函數(shù),我們可以拿來直接使用。 - 標準庫函數(shù)
我們可以通過 import 語句導(dǎo)入庫婿斥,然后使用其中定義的函數(shù) - 第三方庫函數(shù)
Python 社區(qū)也提供了很多高質(zhì)量的庫竖配。下載安裝這些庫后,也是通過 import 語句導(dǎo)
入斩熊,然后可以使用這些第三方庫的函數(shù) - 用戶自定義函數(shù)
函數(shù)的定義和調(diào)用
核心要點
Python 中往枣,定義函數(shù)的語法如下:
def 函數(shù)名 ([參數(shù)列表]) :
'''文檔字符串'''
函數(shù)體/若干語句
Python 執(zhí)行 def 時,會創(chuàng)建一個函數(shù)對象座享,并綁定到函數(shù)名變量上婉商。即函數(shù)也是一個對象
-
參數(shù)列表
(1) 圓括號內(nèi)是形式參數(shù)列表,有多個參數(shù)則使用逗號隔開
(2) 形式參數(shù)不需要聲明類型渣叛,也不需要指定函數(shù)返回值類型
(3) 無參數(shù)丈秩,也必須保留空的圓括號
(4) 實參列表必須與形參列表一一對應(yīng)
-
return 返回值
(1) 如果函數(shù)體中包含 return 語句,則結(jié)束函數(shù)執(zhí)行并返回值淳衙;
(2) 如果函數(shù)體中不包含 return 語句蘑秽,則返回 None 值饺著。
return 返回值要點:
- 如果函數(shù)體中包含 return 語句,則結(jié)束函數(shù)執(zhí)行并返回值肠牲;
- 如果函數(shù)體中不包含 return 語句幼衰,則返回 None 值。
- 要返回多個返回值缀雳,使用列表渡嚣、元組、字典肥印、集合將多個值“存起來”即可识椰。
文檔字符串(函數(shù)的注釋)
通過三個單引號或者三個雙引號來實現(xiàn),中間可以加入多行文字進行說明深碱。
調(diào)用 help(函數(shù)名.__doc__)可以打印輸出函數(shù)的文檔字符串
變量的作用域( 全局變量和局部變量)
全局變量:
在函數(shù)和類定義之外聲明的變量腹鹉。作用域為定義的模塊,從定義位置開始直到模塊
結(jié)束敷硅。全局變量降低了函數(shù)的通用性和可讀性功咒。應(yīng)盡量避免全局變量的使用。
全局變量一般做常量使用绞蹦。
-
函數(shù)內(nèi)要改變?nèi)肿兞康闹盗Ψ埽褂?global 聲明一下
global a #如果要在函數(shù)內(nèi)改變?nèi)肿兞康闹担黾?global 關(guān)鍵字聲明
局部變量:
- 在函數(shù)體中(包含形式參數(shù))聲明的變量坦辟。
- 局部變量的引用比全局變量快刊侯,優(yōu)先考慮使用。
- 如果局部變量和全局變量同名锉走,則在函數(shù)內(nèi)隱藏全局變量滨彻,只使用同名的局部變量
參數(shù)的傳遞
函數(shù)的參數(shù)傳遞本質(zhì)上就是:從實參到形參的賦值操作。 Python 中“一切皆對象”挪蹭,
所有的賦值操作都是“引用的賦值”亭饵。所以,Python 中參數(shù)的傳遞都是“引用傳遞”梁厉,不
是“值傳遞”辜羊。具體操作時分為兩類:
- 對“可變對象”進行“寫操作”,直接作用于原對象本身词顾。
- 對“不可變對象”進行“寫操作”八秃,會產(chǎn)生一個新的“對象空間”,并用新的值填
充這塊空間肉盹。(起到其他語言的“值傳遞”效果昔驱,但不是“值傳遞”)
可變對象:
字典、列表上忍、集合骤肛、自定義的對象等
不可變對象:
數(shù)字纳本、字符串、元組腋颠、function 等
傳遞可變對象的引用
傳遞參數(shù)是可變對象(例如:列表繁成、字典、自定義的其他可變對象等)淑玫,實際傳遞的還是對
象的引用巾腕。在函數(shù)體中不創(chuàng)建新的對象拷貝,而是可以直接修改所傳遞的對象
傳遞可變對象的引用
傳遞參數(shù)是可變對象混移,實際傳遞的還是對象的引用祠墅。在函數(shù)體中不創(chuàng)建新的對象拷貝,而是可以直接修改所傳遞的對象歌径。
a = 100
def f1(n):
print("n:",id(n)) #傳遞進來的是 a 對象的地址
n = n+200 #由于 a 是不可變對象,因此創(chuàng)建新的對象 n
print("n:",id(n)) #n 已經(jīng)變成了新的對象
print(n)
f1(a)
print("a:",id(a)
執(zhí)行結(jié)果:
n: 1663816464
n: 46608592
300
a: 1663816464
淺拷貝和深拷貝
內(nèi)置函數(shù):copy(淺拷貝)亲茅、deepcopy(深拷貝)回铛。
淺拷貝:不拷貝子對象的內(nèi)容,只是拷貝子對象的引用克锣。
深拷貝:會連子對象的內(nèi)存也全部拷貝一份茵肃,對子對象的修改不會影響源對象
傳遞不可變對象包含的子對象是可變的情況
傳遞不可變對象時。不可變對象里面包含的子對象是可變的袭祟。則方法內(nèi)修改了這個可變對象验残,源對象也發(fā)生了變化
參數(shù)的幾種類型
位置參數(shù)
函數(shù)調(diào)用時,實參默認按位置順序傳遞巾乳,需要個數(shù)和形參匹配您没。按位置傳遞的參數(shù),稱為:“位置參數(shù)”胆绊。
默認值參數(shù)
我們可以為某些參數(shù)設(shè)置默認值氨鹏,這樣這些參數(shù)在傳遞時就是可選的。稱為“默認值參數(shù)”压状。默認值參數(shù)放到位置參數(shù)后面仆抵。
命名參數(shù)
我們也可以按照形參的名稱傳遞參數(shù),稱為“命名參數(shù)”种冬,也稱“關(guān)鍵字參數(shù)”镣丑。參數(shù)傳遞順序可變
可變參數(shù)
可變參數(shù)指的是“可變數(shù)量的參數(shù)”。分兩種情況:
*param(一個星號)娱两,將多個參數(shù)收集到一個“元組”對象中莺匠。
-
**param(兩個星號),將多個參數(shù)收集到一個“字典”對象中谷婆。
def f1(a,b,*c): print(a,b,c) f1(8,9,19,20) def f2(a,b,**c): print(a,b,c) f2(8,9,name='gaoqi',age=18) def f3(a,b,*c,**d): print(a,b,c,d) f3(8,9,20,30,name='gaoqi',age=18
強制命名參數(shù)
在帶星號的“可變參數(shù)”后面增加新的參數(shù)慨蛙,必須在調(diào)用的時候“強制命名參數(shù)”
lambda 表達式和匿名函數(shù)
lambda 表達式可以用來聲明匿名函數(shù)辽聊。lambda 函數(shù)是一種簡單的、在同一行中定義函數(shù)
的方法期贫。lambda 函數(shù)實際生成了一個函數(shù)對象跟匆。
lambda 表達式只允許包含一個表達式,不能包含復(fù)雜語句通砍,該表達式的計算結(jié)果就是函數(shù)
的返回值
lambda 表達式的基本語法如下:
lambda arg1,arg2,arg3... : <表達式>
arg1/arg2/arg3 為函數(shù)的參數(shù)玛臂。<表達式>相當于函數(shù)體。運算結(jié)果是:表達式的運算結(jié)果封孙。
eval()函數(shù)
功能:將字符串 str 當成有效的表達式來求值并返回計算結(jié)果迹冤。
nonlocal 關(guān)鍵字
nonlocal 用來聲明外層的局部變量。
global 用來聲明全局變量
LEGB 規(guī)則
Python 在查找“名稱”時虎忌,是按照 LEGB 規(guī)則查找的:
Local-->Enclosed-->Global-->Built in
Local 指的就是函數(shù)或者類的方法內(nèi)部
Enclosed 指的是嵌套函數(shù)(一個函數(shù)包裹另一個函數(shù)泡徙,閉包)
Global 指的是模塊中的全局變量
Built in 指的是 Python 為自己保留的特殊名稱。
對象
類
類的定義
定義類的語法格式:
class 類名:
類體
- 類名必須符合“標識符”的規(guī)則膜蠢;一般規(guī)定堪藐,首字母大寫,多個單詞使用“駝峰原則”挑围。
- 類體中我們可以定義屬性和方法礁竞。
- 屬性用來描述數(shù)據(jù),方法(即函數(shù))用來描述這些數(shù)據(jù)相關(guān)的操作杉辙。
__init__構(gòu)造方法和__new__方法
類是抽象的模捂,也稱之為“對象的模板”。
__init__()的要點如下:
- 名稱固定蜘矢,必須為:__init__()
- 第一個參數(shù)固定狂男,必須為:self。 self 指的就是剛剛創(chuàng)建好的實例對象硼端。
- 構(gòu)造函數(shù)通常用來初始化實例對象的實例屬性
- 通過“類名(參數(shù)列表)”來調(diào)用構(gòu)造函數(shù)
- __init__()方法:初始化創(chuàng)建好的對象并淋,初始化指的是:“給實例屬性賦值”
- __new__()方法: 用于創(chuàng)建對象,但我們一般無需重定義該方法珍昨。
- 如果我們不定義__init__()方法县耽,系統(tǒng)會提供一個默認的__init__()方法。如果我們定義了帶參
的__init__()方法镣典,系統(tǒng)不創(chuàng)建默認的__init__()方法兔毙。
注:
Python 中的 self 相當于 C++中的 self 指針,JAVA 和 C#中的 this 關(guān)鍵字兄春。
Python 中澎剥,self 必須為構(gòu)造函數(shù)的第一個參數(shù),名字可以任意修改赶舆。但一般遵守慣例哑姚,都叫做 self祭饭。
實例屬性和實例方法
實例屬性
實例屬性是從屬于實例對象的屬性,也稱為“實例變量”叙量。
使用要點:
實例屬性一般在\__init__()方法中通過如下代碼定義:
self.實例屬性名 = 初始值在本類的其他實例方法中倡蝙,也是通過 self 進行訪問:
self.實例屬性名-
創(chuàng)建實例對象后,通過實例對象訪問:
obj01 = 類名() #創(chuàng)建對象绞佩,調(diào)用__init__()初始化屬性 obj01.實例屬性名 = 值 #可以給已有屬性賦值寺鸥,也可以新加屬性
實例方法
實例方法是從屬于實例對象的方法。實例方法的定義格式如下:
def 方法名(self [, 形參列表]):
函數(shù)體
方法的調(diào)用格式如下:
對象.方法名([實參列表])
要點:
- 定義實例方法時品山,第一個參數(shù)必須為 self胆建。和前面一樣,self 指當前的實例對象肘交。
- 調(diào)用實例方法時笆载,不需要也不能給 self 傳參。self 由解釋器自動傳參酸些。
函數(shù)和方法的區(qū)別
- 都是用來完成一個功能的語句塊宰译,本質(zhì)一樣。
- 方法調(diào)用時魄懂,通過對象來調(diào)用。方法從屬于特定實例對象闯第,普通函數(shù)沒有這個特點市栗。
- 直觀上看,方法定義時需要傳遞 self咳短,函數(shù)不需要填帽。
其他操作:
- dir(obj)可以獲得對象的所有屬性、方法
- obj._dict_ 對象的屬性字典
- pass 空語句
- isinstance(對象,類型) 判斷“對象”是不是“指定類型”
類對象咙好、類屬性篡腌、類方法、靜態(tài)方法
類對象
類對象的類型就是type
pass 為空語句勾效。就是表示什么都不做嘹悼,只是作為一個占位符存在。當你寫代碼時层宫,
遇到暫時不知道往方法或者類中加入什么時杨伙,可以先用 pass 占位,后期再補上萌腿。
類屬性
類屬性是從屬于“類對象”的屬性限匣,也稱為“類變量”。由于毁菱,類屬性從屬于類對象米死,可以
被所有實例對象共享锌历。
類屬性的定義方式:
class 類名:
類變量名= 初始值
class Student:
company = "SXT" #類屬性
count = 0 #類屬性
def __init_(self,name,score):
self.name = name #實例屬性
self.score = scor
類方法
類方法是從屬于“類對象”的方法。類方法通過裝飾器@classmethod 來定義峦筒,格式如下:
@classmethod
def 類方法名(cls [究西,形參列表]) :
函數(shù)體
要點如下:
- @classmethod 必須位于方法上面一行
- 第一個 cls 必須有;cls 指的就是“類對象”本身勘天;
- 調(diào)用類方法格式:“類名.類方法名(參數(shù)列表)”怔揩。 參數(shù)列表中,不需要也不能給 cls 傳
值脯丝。 - 類方法中訪問實例屬性和實例方法會導(dǎo)致錯誤
- 子類繼承父類方法時商膊,傳入 cls 是子類對象,而非父類對象
靜態(tài)方法
Python 中允許定義與“類對象”無關(guān)的方法宠进,稱為“靜態(tài)方法”晕拆。
“靜態(tài)方法”和在模塊中定義普通函數(shù)沒有區(qū)別,只不過“靜態(tài)方法”放到了“類的名字空
間里面”材蹬,需要通過“類調(diào)用”实幕。
靜態(tài)方法通過裝飾器@staticmethod 來定義,格式如下:
@staticmethod
def 靜態(tài)方法名([形參列表]) :
函數(shù)體
要點如下:
- @staticmethod 必須位于方法上面一行
- 調(diào)用靜態(tài)方法格式:“類名.靜態(tài)方法名(參數(shù)列表)”堤器。
- 靜態(tài)方法中訪問實例屬性和實例方法會導(dǎo)致錯誤
__del__方法(析構(gòu)函數(shù))和垃圾回收機制
__del__方法稱為“析構(gòu)方法”昆庇,用于實現(xiàn)對象被銷毀時所需的操作。
__del__方法稱為“析構(gòu)方法”闸溃,用于實現(xiàn)對象被銷毀時所需的操作整吆。
可以通過 del 語句刪除對象,從而保證調(diào)用__del__方法辉川。系統(tǒng)會自動提供__del__方法表蝙,一般不需要自定義析構(gòu)方法。
__call__方法和可調(diào)用對象
定義了__call__方法的對象乓旗,稱為“可調(diào)用對象”府蛇,即該對象可以像函數(shù)一樣被調(diào)用。
class SalaryAccount:
def __call__(self, salary):
yearSalary = salary*12
daySalary = salary//30
hourSalary = daySalary//8
return dict(monthSalary=salary,yearSalary=yearSalary,daySalary=daySalary,hourSalary=hourSalary)
s = SalaryAccount()
print(s(5000)
{'monthSalary': 5000, 'yearSalary': 60000, 'daySalary': 166, 'hourSalary': 20}
方法沒有重載
Python 中屿愚,方法的的參數(shù)沒有聲明類型(調(diào)用時確定參數(shù)的類型)汇跨,參數(shù)的數(shù)量也可以由
可變參數(shù)控制。
不要使用重名的方法渺鹦!Python 中方法沒有重載
方法的動態(tài)性
Python 是動態(tài)語言扰法,我們可以動態(tài)的為類添加新的方法,或者動態(tài)的修改類的已有的方法毅厚。
Python 一切皆對象
私有屬性和私有方法(實現(xiàn)封裝)
Python 對于類的成員沒有嚴格的訪問控制限制塞颁,這與其他面向?qū)ο笳Z言有區(qū)別。關(guān)于私有
屬性和私有方法,有如下要點:
- 通常我們約定祠锣,兩個下劃線開頭的屬性是私有的(private)酷窥。其他為公共的(public)。
- 類內(nèi)部可以訪問私有屬性(方法)
- 類外部不能直接訪問私有屬性(方法)
- 類外部可以通過“_類名__私有屬性(方法)名”訪問私有屬性(方法)p._Employee__age
@property 裝飾器
@property 可以將一個方法的調(diào)用方式變成“屬性調(diào)用”伴网。
class Employee
def __init__(self,name,salary):
self.name = name
self.__salary = salary
@property #相當于 salary 屬性的 getter 方法
def salary(self):
print("月薪為{0},年薪為{1}".format(self.__salary,(12*self.__salary)))
return self.__salary;
@salary.setter
def salary(self,salary): #相當于 salary 屬性的 setter 方法
if(0<salary<1000000):
self.__salary = salary
else:
print("薪水錄入錯誤蓬推!只能在 0-1000000 之間"
面向?qū)ο?/h1>
繼承
語法格式
Python 支持多重繼承,一個子類可以繼承多個父類澡腾。繼承的語法格式如下:
class 子類類名(父類 1[沸伏,父類 2,...]):
類體
默認父類是 object 類
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age
class Student(Person):
def __init__(self,name,age,score):
self.score = score
Person.__init__(self,name,age) #構(gòu)造函數(shù)中包含調(diào)用父類構(gòu)造函數(shù)动分。根據(jù)需要毅糟,不是必須。
子類并不會自動調(diào)用父類的\_\_init\_\_()澜公,我們必須顯式的調(diào)用
類成員的繼承和重寫
- 成員繼承:子類繼承了父類除構(gòu)造方法之外的所有成員姆另。
- 方法重寫:子類可以重新定義父類中的方法,這樣就會覆蓋父類的方法坟乾,也稱為“重寫”
重寫__str__()方法
object 有一個__str__()方法迹辐,用于返回一個對于“對象的描述”,對應(yīng)于內(nèi)置函數(shù) str()
經(jīng)常用于 print()方法甚侣,幫助我們查看對象的信息明吩。__str__()可以重寫。
多重繼承
Python 支持多重繼承殷费,一個子類可以有多個“直接父類”贺喝。這樣,就具備了“多個父類”的特點宗兼。但是由于這樣會被“類的整體層次”搞的異常復(fù)雜,盡量避免使用氮采。
MRO()
Python 支持多繼承殷绍,如果父類中有相同名字的方法,在子類沒有指定父類名時鹊漠,解釋器將
“從左向右”按順序搜索主到。
MRO(Method Resolution Order):方法解析順序。 我們可以通過 mro()方法獲得
“類的層次結(jié)構(gòu)”躯概,方法解析順序也是按照這個“類的層次結(jié)構(gòu)”尋找的登钥。
super()獲得父類定義
在子類中,如果想要獲得父類的方法時娶靡,我們可以通過 super()來做牧牢。
super()代表父類的定義,不是父類對象。
多態(tài)
多態(tài)(polymorphism)是指同一個方法調(diào)用由于對象不同可能會產(chǎn)生不同的行為塔鳍。
- 多態(tài)是方法的多態(tài)伯铣,屬性沒有多態(tài)。
- 多態(tài)的存在有 2 個必要條件:繼承轮纫、方法重寫腔寡。
特殊方法和運算符重載
Python 的運算符實際上是通過調(diào)用對象的特殊方法實現(xiàn)的。
常見的特殊方法統(tǒng)計如下:
方法 說明 例子
__init__ 構(gòu)造方法 對象創(chuàng)建:p = Person()
__del__ 析構(gòu)方法 對象回收
__repr__,__str__ 打印掌唾,轉(zhuǎn)換 print(a)
__call__ 函數(shù)調(diào)用 a()
__getattr__ 點號運算 a.xxx
__setattr__ 屬性賦值 a.xxx = value
__getitem__ 索引運算 a[key]
__setitem__ 索引賦值 a[key]=value
__len__ 長度 len(a)
運算符 特殊方法 說明
運算符+ __add__ 加法
運算符- __sub__ 減法
<,<=,== __lt__,__le__放前,__eq__ 比較運算符
>,>=,!= __gt__,__ge__,__ne__ 比較運算符
|,^,& __or__,__xor__,__and__ 或、異或糯彬、與
<<,>> __lshift__,__rshift__ 左移凭语、右移
*,/,%,// __mul__,__truediv__,__mod__,__floordiv__ 乘、浮除情连、模運算
(取余)叽粹、整數(shù)除
** __pow__ 指數(shù)運算
每個運算符實際上都對應(yīng)了相應(yīng)的方法
特殊屬性
Python 對象中包含了很多雙下劃線開始和結(jié)束的屬性,這些是特殊屬性却舀,有特殊用法
特殊方法 含義
obj.__dict__ 對象的屬性字典
obj.__class__ 對象所屬的類
class.__bases__ 類的基類元組(多繼承)
class.__base__ 類的基類
class.__mro__ 類層次結(jié)構(gòu)
class.__subclasses__() 子類列表
對象的淺拷貝和深拷貝
- 變量的賦值操作
只是形成兩個變量虫几,實際還是指向同一個對象。
- 淺拷貝
Python 拷貝一般都是淺拷貝挽拔×玖常拷貝時,對象包含的子對象內(nèi)容不拷貝螃诅。因此啡氢,源對象
和拷貝對象會引用同一個子對象。
- 深拷貝
使用 copy 模塊的 deepcopy 函數(shù)术裸,遞歸拷貝對象中包含的子對象倘是。源對象和拷貝對象
所有的子對象也不同
組合
is-a”關(guān)系,我們可以使用“繼承”袭艺。從而實現(xiàn)子類擁有的父類的方法和屬性搀崭。
“has-a”關(guān)系,我們可以使用“組合”猾编,也能實現(xiàn)一個類擁有另一個類的方法和屬性瘤睹。
設(shè)計模式_工廠模式實現(xiàn)
工廠模式實現(xiàn)了創(chuàng)建者和調(diào)用者的分離,使用專門的工廠類將選擇實現(xiàn)類答倡、創(chuàng)建對象進行統(tǒng)一的管理和控制轰传。
class CarFactory:
def createCar(self,brand):
if brand == "奔馳":
return Benz()
elif brand == "寶馬":
return BMW()
elif brand == '比亞迪':
return BYD()
else:
return "未知品牌,無法創(chuàng)建"
class Benz:
pass
class BMW:
pass
class BYD:
pass
factory = CarFactory()
c1 = factory.createCar("奔馳")
c2 = factory.createCar("寶馬")
設(shè)計模式_單例模式實現(xiàn)
單例模式(Singleton Pattern)的核心作用是確保一個類只有一個實例瘪撇,并且提供一個訪問該實例的全局訪問點获茬。
class MySingleton:
__obj = None
__init_flag = True
def __new__(cls, *args, **kwargs):
if cls.__obj == None:
cls.__obj = object.__new__(cls) # 創(chuàng)建父類對象
return cls.__obj
def __init__(self,name):
if MySingleton.__init_flag: # 保證初始化只執(zhí)行一次
print( "init....")
self.name = name
MySingleton.__init_flag = False
a = MySingleton( "aa")
print(a)
b = MySingleton( "bb")
print(b)
異常
在執(zhí)行程序的時候遇到錯誤港庄,會停止程序的執(zhí)行,并提示錯誤信息锦茁,這就是異常
捕獲異常
語法格式:
try:
# 嘗試執(zhí)行的代碼
except:
# 出現(xiàn)錯誤的處理
捕獲特殊錯誤類型
程序運行出錯的第一個單詞攘轩,就是錯誤類型
try:
# 嘗試執(zhí)行的代碼
pass
except 錯誤類型1:
# 出現(xiàn)錯誤類型1的處理
pass
except (錯誤類型2, 錯誤類型3):
# 出現(xiàn)錯誤類型2或者錯誤類型3的處理
pass
捕獲未知錯誤
except Exception as result: # result變量接收錯誤信息
print("未知錯誤 %s" % result)
異常捕獲完整語法
try:
pass
except ValueError:
pass
except Exception as result:
pass
else:
# 沒有異常執(zhí)行的代碼
pass
finally:
# 無論是否出現(xiàn)異常,都會執(zhí)行码俩。最后執(zhí)行
pass
異常的傳遞
當函數(shù)/方法出現(xiàn)錯誤時度帮,會把異常傳遞給函數(shù)/方法的調(diào)用處,直到主程序
當異常拋出到主程序時稿存,仍然沒有進行異常捕獲笨篷,程序就會終止
利用異常的傳遞性,可以在主程序中捕獲異常
拋出raise異常
創(chuàng)建一個Exception的對象
-
使用raise關(guān)鍵字拋出異常對象
# 創(chuàng)建異常對象 ex = Exception("異常描述信息") # 主動拋出異常 raise ex # raise + 異常對象
模塊
模塊的導(dǎo)入
import導(dǎo)入
模塊導(dǎo)入關(guān)鍵字import瓣履,導(dǎo)入模塊應(yīng)該單行導(dǎo)入一個模塊
模塊名.的方式使用模塊中提供的類率翅,全局變量,函數(shù)
使用關(guān)鍵字as指定模塊的別名袖迎,別名命名方法使用大駝峰命名法(單個單詞首字母大寫)
import 模塊名 as 模塊名
from...import導(dǎo)入
從一個模塊中冕臭,導(dǎo)入部分工具
from 模塊名 import 工具名
通過from導(dǎo)入之后,不需要通過模塊名.的方式來使用燕锥」脊螅可以直接使用工具名進行使用
注意:如果兩個模塊,存在同名的函數(shù)归形,那么后導(dǎo)入的函數(shù)鞭缭,會覆蓋掉之前導(dǎo)入的函數(shù)贱案。
一旦發(fā)現(xiàn)有同名的函數(shù)你雌,可以使用as指定別名
模塊的搜索順序
- 搜索當前目錄指定模塊名的文件尤仍,如果有就直接導(dǎo)入
- 如果沒有,再搜索系統(tǒng)目錄
__name__屬性
文件被導(dǎo)入時蔼紧,能夠直接執(zhí)行的代碼不需要被執(zhí)行婆硬!因此需要使用__name__屬性來做判斷。
__name__是Python的一個內(nèi)置屬性奸例,記錄著一個字符串.
如果是被其他文件導(dǎo)入的柿祈,__name__就是模塊名
如果是當前執(zhí)行的程序__name__就是__main__
Python文件的標準代碼格式:
# 導(dǎo)入模塊
# 定義全局變量
# 定義類
# 定義函數(shù)
def main():
pass
# 根據(jù)__name__屬性判斷是否需要執(zhí)行代碼
if __name__="__main__"
main()
包
- 包是一個包含多個模塊的特殊目錄
- 目錄下有一個特殊文件:__init__.py
- 包的命名方式和變量名一樣,小寫字母+下劃線
使用import 包名 可以一次性導(dǎo)入包中的所有模塊
__init__.py
要在外界使用包中的模塊哩至,需要在__init__.py文件中指定對外界提供的模塊列表
from . import 模塊列表
發(fā)布模塊
將自己開發(fā)的模塊,分享給其他人
制作發(fā)布壓縮包
安裝刪除模塊
pip安裝刪除模塊
文件
文件操作步驟
- 打開文件 open()
- 讀寫文件 read() write()
- 關(guān)閉文件 close()
read()函數(shù)運行之后會將指針移動到文件末尾蜜自,再次讀的話是讀取不到內(nèi)容的
文件復(fù)制
小文件
小文件直接復(fù)制
file = open("move.json", encoding="utf-8")
text = file.read()
copyFile = open("copyMove.json", mode="w", encoding="utf-8")
copyFile.write(text)
file.close()
copyFile.close()
大文件
大文件需要逐行復(fù)制
file = open("move.json", encoding="utf-8")
copyFile = open("copyMove.json", mode="w", encoding="utf-8")
while True:
text = file.readline() # 逐行讀取
if not text:
break
copyFile.write(text)
file.close()
copyFile.close()
文件操作
文件操作需要導(dǎo)入os模塊
rename() 重命名
remove() 刪除文件
# 文件重命名
os.rename("copyMove.json", "reNameCopyMove.json")
# 刪除文件
os.remove("reNameCopyMove.json")
文本編碼格式
- Python2.x 默認是ASCII編碼格式
- Python3.x 默認是UTF-8編碼格式 (UTF-8是Unicode的一種)
Python2.x 中第一行增加一行代碼注釋就可以處理Python文件中的中文導(dǎo)致的錯誤
# *-* coding:utf8 *-* 官方推薦
# coding = utf8
eval函數(shù)
eval()函數(shù)將字符串當成有效的表達式菩貌,并返回計算結(jié)果
print(eval("1+1")) # 輸出2
eval函數(shù)不要濫用,不要直接轉(zhuǎn)換input結(jié)果
網(wǎng)絡(luò)編程
IP地址
目的:用來標記網(wǎng)絡(luò)上的一臺設(shè)備(唯一)
dest_ip 目標IP
src_ip 源IP
ip地址的分類
IP地址由四組數(shù)字組成 (0-255)
端口
dest_port 目標端口
src_port 源端口
用來標識PC的應(yīng)用進程
知名端口
知名端口0-1023 動態(tài)端口從1024-65535
80端口http服務(wù) 21端口分配給FTP服務(wù)
socket
import socket
# 創(chuàng)建一個socket UDP
udp_socket = socket.socketpair(socket.AF_INET, socket.SOCK_DGRAM)
# 綁定端口號
udp_socket.bind("端口號")
# 使用套接字收發(fā)數(shù)據(jù) 數(shù)據(jù)和對方的IP地址以及端口號
udp_socket.sendto("數(shù)據(jù)", ("192.158.33.23", 8080))
udp_socket.close()
UDP收發(fā)收據(jù)
同一個套接字可以收發(fā)數(shù)據(jù)
import socket
# UDP聊天器重荠,并保存聊天記錄
def main():
# 創(chuàng)建一個socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
file = open("chatRecord.txt", mode="a", encoding="utf-8")
while True:
print("UDP聊天器")
print("輸入0結(jié)束程序")
print("輸入1發(fā)送數(shù)據(jù)")
print("輸入2接收數(shù)據(jù)")
input_data = int(input())
if 0 == input_data:
file.close()
break
elif 1 == input_data:
file.write(str(send_data(udp_socket)) + "\n")
elif 2 == input_data:
file.write(str(receive_data(udp_socket)) + "\n")
else:
print("輸入錯誤")
udp_socket.close()
# socket 接收數(shù)據(jù)
def receive_data(udp_socket):
receive_data = udp_socket.recvfrom(1024)
print("發(fā)送者:%s\n發(fā)送內(nèi)容:%s" % (str(receive_data[1]), receive_data[0].decode("gbk")))
return "發(fā)送者:%s\n發(fā)送內(nèi)容:%s" % (str(receive_data[1]), receive_data[0].decode("gbk"))
# 使用套接字發(fā)送數(shù)據(jù)
def send_data(udp_socket):
dest_ip = input("請輸入對方的ip地址:")
dest_port = int(input("請輸入對方的端口號:"))
send_data = input("請輸入要聊天的內(nèi)容:")
udp_socket.sendto(send_data.encode("gbk"), (dest_ip, dest_port))
return str(send_data.encode("utf-8"), encoding="utf-8")
if __name__ == '__main__':
main()
TCP
TCP客戶端收發(fā)數(shù)據(jù)
import socket
def main():
# 創(chuàng)建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket.bind(("", 7788))
# 連接服務(wù)器
tcp_socket.connect(("192.168.28.90", 8080))
send_data = input("請輸入要發(fā)送的內(nèi)容:")
# 發(fā)送數(shù)據(jù)
tcp_socket.send(send_data.encode("gbk"))
# 接收數(shù)據(jù)
receive_data = tcp_socket.recvfrom(1024)
print("發(fā)送者:%s\n發(fā)送內(nèi)容:%s" % (receive_data[1], receive_data[0].decode("gbk")))
# 關(guān)閉套接字
tcp_socket.close()
if __name__ == '__main__':
main()
TCP服務(wù)端收發(fā)數(shù)據(jù)
import socket
# 創(chuàng)建socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 綁定端口信息
tcp_server_socket.bind(("", 7000))
tcp_server_socket.listen(128)
new_client_socket, client_address = tcp_server_socket.accept()
print(client_address)
receive_data = new_client_socket.recv(1024)
print(receive_data.decode("gbk"))
new_client_socket.send("收到信息啦...".encode("gbk"))
new_client_socket.close()
tcp_server_socket.close()
多任務(wù)
多線程
線程執(zhí)行的順序不確定
調(diào)用線程的start()方法時才會創(chuàng)建線程箭阶,以及運行線程
import time
import threading
def sing():
for i in range(5):
print("------唱歌--------")
time.sleep(1)
def dance():
for i in range(5):
print("=========跳舞========")
time.sleep(1)
def main():
sing_thread = threading.Thread(target=sing) # 注意這里是要用函數(shù)名,不能用函數(shù)名()->這個是調(diào)用函數(shù)
dance_thread = threading.Thread(target=dance)
sing_thread.start()
dance_thread.start()
if __name__ == '__main__':
main()
多線程共享全局變量
全局變量的的修改:
在一個函數(shù)中對全局變量進行修改的時候,到底是否需要使用global進行說明,要看是否對全局變量的指向進行了修改
如果修改了指向仇参,即全局變量指向了一個新的地方嘹叫,那么必須使用global
如果僅僅是修改了指向空間中的數(shù)據(jù),此時不用使用global
多線程共享全局變量會導(dǎo)致資源競爭問題
互斥鎖
lock = threading.Lock() #創(chuàng)建鎖
lock.acquire() # 上鎖
lock.release() # 釋放鎖