Python爬蟲快速實(shí)戰(zhàn)
目標(biāo): 通過(guò)四天的學(xué)習(xí)蔬将,具備爬蟲(Python)初級(jí)工程師的能力,勝任接口(API)自動(dòng)化測(cè)試擅威、數(shù)據(jù)采集(爬蟲)的崗位要求盆驹。
第一天:Python基礎(chǔ)
Python的編程環(huán)境: 3.6/3.7
交互式環(huán)境:命令行(cmd)中直接輸入python 【回車】后進(jìn)入交互式環(huán)境,此環(huán)境中直接執(zhí)行python指令居凶。
腳本: 通過(guò)記事本(文本編緝器)編寫python腳本文件虫给,通過(guò)python解釋器環(huán)境(Pycharm工具)來(lái)執(zhí)行腳本,并顯示執(zhí)行的結(jié)果侠碧。
1.1 數(shù)據(jù)類型
1.1.1 基本數(shù)據(jù)類型
int 整型抹估, 如1, 2, 3等
float 浮點(diǎn)(小數(shù))類型, 如1.15, 3.14等
str 字符類型弄兜, 如'祁老師真帥', "disen在西安校區(qū)等你"药蜻。單引號(hào)或雙引號(hào)必段是英文字符。
bytes 字節(jié)類型, 如 b'123', b'abc'替饿。字節(jié)類型用于文件流语泽、網(wǎng)絡(luò)流的傳輸。通過(guò)str.encode()函數(shù)视卢,將字符串轉(zhuǎn)成字節(jié)數(shù)據(jù)踱卵,一般指定encode()函數(shù)中的encoding參數(shù),表示字符的編碼類型腾夯,默認(rèn)UTF-8(Python3.7)颊埃∈叱洌可以通過(guò)bytes.decode(encoding=None)函數(shù)蝶俱,將字節(jié)數(shù)據(jù)轉(zhuǎn)成字符串。
bool 布爾類型饥漫, True 真榨呆, False假, 可以通過(guò)int(bool值)轉(zhuǎn)成整型,F(xiàn)alse ->0 , True -> 1, 通過(guò)bool(obj)將obj對(duì)象轉(zhuǎn)換成布爾值庸队。
【注意】None 類似于C的空指針积蜻,表示未知。SyntaxError
語(yǔ)法錯(cuò)誤(異常)彻消。
type(obj)函數(shù)主要獲取obj對(duì)象的類型竿拆, 屬于Python自省函數(shù)的成員,也是創(chuàng)建類對(duì)象的類(元類)宾尚。
help(obj.func_name) 查看對(duì)象的某一函數(shù)的幫助文檔丙笋, 如 help(bytes.decode), help(str.encode), 按Q鍵退出谢澈。
練習(xí):
bool(0) -> False
bool('') -> False
bool('a') -> True
bool(None) -> False
1.1.2 集合類型
由多個(gè)基本類型的數(shù)據(jù)組成的對(duì)象的結(jié)構(gòu),稱之為集合類型御板。
list 列表類型锥忿, 如 [1,2, 3], 和c或java語(yǔ)言中列表或數(shù)組有區(qū)別怠肋,列表中的元素可以是任意類型敬鬓,而數(shù)組的類型是固定的。
tuple 元組笙各, 如(1, 2, 3)
dict 字典钉答, 如{‘id’: '1001', 'name': 'disen'}
# list元素類型的示例
person = ['1001', 'disen', 20, 190, 99.5, ['編程', '看電影', '約會(huì)']]
# 索引操作, obj[索引下標(biāo)], Python的索引下標(biāo)從0開(kāi)始(從左開(kāi)始),負(fù)號(hào)表示從右開(kāi)始(-1 開(kāi)始)杈抢。
person[0]
person[2]
person[-1] 最后一個(gè)元素
person[-1][-1] 獲取最后一個(gè)列表元素中的最后一個(gè)元素
person[-2] 倒數(shù)第二個(gè)元素
# 索引切片操作 obj[起始位置:結(jié)束位置:步長(zhǎng)]希痴, 默認(rèn): 起始為0, 結(jié)束為最后一個(gè)元素春感, 步長(zhǎng)為1, 如果是-1表示砌创,從右到左切片操作。
person[::-1]
person[2:] 結(jié)果是 [20, 190, 99.5, ['編程', '看電影', '約會(huì)']]
person[2:4] 結(jié)果是 [20, 190] 不包含4索引下標(biāo)的內(nèi)容鲫懒,即[2, 4)區(qū)間嫩实。
person[2:-1] 結(jié)果是 [20, 190, 99.5], 即不包含最后一個(gè)元素。
# 元素操作窥岩, append(元素)追加元素甲献, remove(元素)刪除元素, insert(index, 元素), pop(index)
person.insert(0, 1) 向索引下標(biāo)0位置插入一個(gè) 1元素颂翼,原來(lái)的0下標(biāo)元素整體向右移動(dòng)晃洒。
person.pop(0) 彈出索引下標(biāo)0位置的元素
person.remove('disen') 將disen元素從列表中刪除
person.append('disen') 將disen的元素內(nèi)容追加到列表的末尾。
# 修改元素
person[2] += 2 # 支持修改元素
# tuple 在Python中表示一個(gè)集合常量朦乏,只有聲明時(shí)才能添加元組中的元素球及。定義之后的元組的元素不能修改。
person2 = (1, '1001', 'disen', 190, 99.5)
# 索引操作同列表的索引操作
person2[0]
person2[2:3] 結(jié)果 ('disen',) 元組呻疹, 只有一個(gè)元素時(shí)不能寫成('disen')吃引,因?yàn)樗莾?yōu)先表達(dá)式
person2[0] = 2 # 元組中的元素不能被修改, 解釋器會(huì)拋出 TypeError異常錯(cuò)誤刽锤。
# dict 字典 類似于json格式(JavaScript對(duì)象)【重點(diǎn)】
# 鍵 key, 值 value, dict的結(jié)構(gòu)稱之為鍵值對(duì)
person = {'name': '永琪', 'sex': '男', 'height': 190, 'salary': 100.0}
# 修改字典中的key的值 obj[key] = value
person['name'] = '凌永琪'
person["height"] = 200 # 單位: cm
# 獲取key的值, obj[key], obj.get(key, default_value)
person["salary"] # person['salary']
person.get('salary') 返回value
# .get()獲取key,如果不存在key镊尺,則返回None,當(dāng)然指定返回的default_value默認(rèn)值
# [key] 獲取key時(shí),如果不存在key, 則解釋器拋出異常(KeyError)并思,程序中斷執(zhí)行(發(fā)生錯(cuò)誤之后)
person['salaries']
person.get('salaries')
person.get('salaries', 90)
# dict對(duì)象常用的方法
.values() 返回所有value的列表
.keys() 返回所有key的列表
.items() 返回(key, value)組成的元組結(jié)構(gòu)的列表
.setdefault(key, default_value) 設(shè)置key的默認(rèn)值庐氮,如果key存在,則無(wú)效宋彼, 反之key不存在時(shí)弄砍,有效颅筋。
.pop(key) 彈出key, 實(shí)際上從dict中刪除key
.update(dict) 通過(guò)給定的dict參數(shù)更新原有的字典∈淇荩可以達(dá)到兩個(gè)字典合并的效果议泵。
.clear() 清空字典中所有item項(xiàng)目(key, value)
.copy() 復(fù)制字典,備份字典
【擴(kuò)展】將dict字典對(duì)象轉(zhuǎn)成json格式的字符串(json object {}, json array [])
json模塊桃熄, 導(dǎo)入模塊 `import 模塊名`
json.dumps(dict) 轉(zhuǎn)化為json格式的字符串
json.loads(json_str) 將json格式的字符串轉(zhuǎn)成dict或list對(duì)象
【擴(kuò)展】dir(obj) 查看obj對(duì)象中所有屬性和方法先口, 結(jié)合help(obj.屬性或方法)查看用法說(shuō)明。
練習(xí):
1. 創(chuàng)建水果的字典瞳收, 水果信息包含水果的編號(hào) 碉京、類型或品種、價(jià)格螟深、產(chǎn)地谐宙、規(guī)格(單件或整箱)
>>> fruits={'編號(hào)':1,'類型':'蘋果','價(jià)格':10,'產(chǎn)地':'西安','規(guī)格':'單件'}
2. 查看水果的產(chǎn)地, 并修改為'西安'或`延安`
>>> fruits['產(chǎn)地']
'西安'
>>> fruits['產(chǎn)地']='延安'
>>> fruits['產(chǎn)地']
'延安'
3. 備份水果的字典界弧, 修改原水果的價(jià)格和規(guī)格
>>> new_fruits = fruits.copy()
>>> fruits['價(jià)格']=20
>>> fruits['規(guī)格']='整箱'
>>> fruits
{'編號(hào)': 1, '類型': '蘋果', '價(jià)格': 20, '產(chǎn)地': '延安', '規(guī)格': '整箱'}
1.1.3 類型轉(zhuǎn)換
字符類型 轉(zhuǎn)換 其它類型
'123' -> 123 int('123', base=10) base表示進(jìn)制(2進(jìn)制凡蜻, 8進(jìn)制、10進(jìn)制垢箕、16進(jìn)制)
'1000' -> 8 int('1000', base=2)
'0b1210' ->725520 int('0b1210', base=16)
'1.75' -> 1.75 float('1.75')
'True' -> True bool('True' )
'您好' -> bytes '您好'.encode('utf-8')
其它類型轉(zhuǎn)成字符串類型
str(obj) 將obj對(duì)象數(shù)據(jù)轉(zhuǎn)成str類型划栓, 如果obj是dict類型,轉(zhuǎn)成str之后条获,可以通過(guò)eval()將字符串的字典對(duì)象提取出來(lái)忠荞,執(zhí)行的結(jié)果賦值給指定標(biāo)識(shí)符。
【擴(kuò)展】eval()函數(shù)帅掘,把給定的字符串的內(nèi)容作為Python有效的表達(dá)式執(zhí)行委煤。
eval("a=10+100") # 報(bào)錯(cuò),表達(dá)式中不能出現(xiàn)賦值語(yǔ)句修档。
a = eval("10+100") # 等同于 a = 10+100
dict()函數(shù)和list()函數(shù)
list()將可迭代(Iteration)對(duì)象轉(zhuǎn)成列表碧绞, 集合類型和str都是可迭代的。
dict(key=value, key2=value2) 將指定的參數(shù)和參數(shù)值轉(zhuǎn)成字典
【注】dict也是可迭代的萍悴,默認(rèn)迭代是keys头遭。
>>> person2
{'name': '凌永琪', 'height': 160, 'salary': 100.0, 'weight': 50, 'sex': '女', 'lovies': ['看書', '跑步']}
>>> list(person2)
['name', 'height', 'salary', 'weight', 'sex', 'lovies']
>>> list(person2.keys())
['name', 'height', 'salary', 'weight', 'sex', 'lovies']
>>> list(person.values())
['凌永琪', 160, 100.0, 50, '女', ['看書', '跑步']]
>>> apple = dict(name='青蘋果', price=9.5)
>>> apple
{'name': '青蘋果', 'price': 9.5}
1.2 標(biāo)識(shí)符與運(yùn)算符
標(biāo)識(shí)符(identifier)是指用來(lái)標(biāo)識(shí)某個(gè)實(shí)體的一個(gè)符號(hào),在不同的應(yīng)用環(huán)境下有不同的含義癣诱。在計(jì)算機(jī)編程語(yǔ)言中,標(biāo)識(shí)符是用戶編程時(shí)使用的名字袜香,用于給變量撕予、常量、函數(shù)蜈首、類等命名实抡,以建立起名稱與使用之間的關(guān)系欠母。
1.2.1 標(biāo)識(shí)符的命名規(guī)則
標(biāo)識(shí)符通常由字母和數(shù)字以及其它字符構(gòu)成,在Python中變量名吆寨、腳本名赏淌、包名、函數(shù)名建議使用小寫字符啄清,遇到詞組六水,則以下劃線_
相連,類名使用駝峰命名(首字母大寫)辣卒,如 SystemManager, ClientThread, ServerThread掷贾。
標(biāo)識(shí)符的命名不能使用Python中的關(guān)鍵字,通過(guò)help('keywords')查看python中的關(guān)鍵字荣茫。
1.2.2 Python支持的運(yùn)算符
算術(shù)運(yùn)算符
+ 加法想帅、
- 減法、
* 乘法啡莉、
** 次冪港准、
/ 除法取整和小數(shù)、
// 除法取整咧欣、
% 取余數(shù)
+= 叉趣, -= , *=该押, **=疗杉, /=, //=, %=
a = (23+102-5*20)/15 LaTex數(shù)學(xué)語(yǔ)法
a=round( (2**3+10**2-5*20)/15, 2) # round()四舍五入的函數(shù)
>>> a = (2**3 + 10**2 -5*20)/15
>>> a
0.5333333333333333
>>> a = round((2**3 + 10**2 -5*20)/15,2)
>>> a
0.53
關(guān)系運(yùn)算符**
> 大于
>= 大于等于
< 小于
<= 小于等于
== 內(nèi)容相等
!= 內(nèi)容不相等
is 內(nèi)容和內(nèi)存地址都相等【了解】
is not 內(nèi)容和內(nèi)存地址都不相等
邏輯運(yùn)算符
and 且的關(guān)系,and 兩邊的bool值都為True是蚕礼,則結(jié)果True
or 或的關(guān)系烟具,兩邊有一個(gè)存在True,則結(jié)果為True
not 取反, 對(duì)False取反則為True, 對(duì)True取反則為False
位運(yùn)算符
將數(shù)值轉(zhuǎn)成二進(jìn)制數(shù)據(jù)奠蹬,從低位向高位進(jìn)行計(jì)算朝聋。
bin(數(shù)值) 將10進(jìn)制的數(shù)值轉(zhuǎn)成二制的字符串,如下所示:
b1, b2 = bin(9), bin(10)
1001 9
1010 10
^
= 0011 3
-----------------------
1001 9
1010 10
|
=1011 11
-----------------------
1001 9
1010 10
&
=1000 8
| 位或, 同一位的兩個(gè)數(shù)中任一個(gè)是1囤躁,則為1冀痕,反之為0
& 位與, 同一位的兩個(gè)數(shù)都是1狸演,則為1言蛇,反之為0
^ 位異或, 同一位的兩個(gè)數(shù)不相同時(shí)為1宵距,反之為0
|=
&=
^=
優(yōu)先級(jí)
算術(shù)運(yùn)算 優(yōu)先于 位運(yùn)算和關(guān)系運(yùn)算
位運(yùn)算 優(yōu)先于 關(guān)系運(yùn)算
關(guān)系運(yùn)算 優(yōu)先于 邏輯運(yùn)算
小括號(hào) ( ) 最優(yōu)先
4+5 | 10 > 5 or 10//2 > 3
【注意】Python不支持自增++
或自減--
運(yùn)算符腊尚。
1.3 分支與循環(huán)
1.3.1 if分支語(yǔ)句
if 邏輯表達(dá)式:
表達(dá)式結(jié)果為True的語(yǔ)句塊
else:
表達(dá)式結(jié)果為False的語(yǔ)句塊
n1 = int(input('輸入一個(gè)數(shù)字:'))
if n1 > 10:
print('輸入的數(shù)字大于10') # 行前向右縮進(jìn)了2個(gè)空格
else:
print('輸入的數(shù)字小于10') # 同一層的縮進(jìn)空格的數(shù)量保持一致
if 邏輯表達(dá)式:
表達(dá)式結(jié)果為True的語(yǔ)句塊
elif 邏輯表達(dá)式2:
表達(dá)式2結(jié)果為True的語(yǔ)句塊
elif 邏輯表達(dá)式3:
表達(dá)式3結(jié)果為True的語(yǔ)句塊
else:
最近表達(dá)式結(jié)果為False的語(yǔ)句塊
import random # 隨機(jī)模塊
# n1 = float(input('輸入本次考試的成績(jī):'))
n1 = random.randint(0, 100)
if n1 > 90:
print('A')
elif n1 > 80:
print('B')
elif n1 > 70:
print('C')
elif n1 > 60:
print('D')
else:
print('你的成績(jī)太差了, 重學(xué)一年')
1.3.2 if分支表達(dá)式
在Python中的三元表達(dá)式使用 if 和else分支表達(dá)式满哪,如下所示:
select_opt = int(input('輸入你的選擇: 0 退出婿斥, 1 重新開(kāi)始'))
cmd = 'exit' if select_opt == 0 else 'restart'
類似于java中的三目運(yùn)算符條件?為true值:為假的值
1.3.3 while循環(huán)
while 邏輯表達(dá)式:
循環(huán)執(zhí)行語(yǔ)句
[改變條件表達(dá)式中變量值]
[如果邏輯表達(dá)式直接為True,則存在退出循環(huán)的條件判斷]
[continue | break]
s,i = 0, 1
while i <= 10:
s += i # 計(jì)算10以內(nèi)數(shù)值和
i += 1
print(s) # 55
# 練習(xí): 計(jì)算100以內(nèi)除了3的陪數(shù)以外的所有數(shù)的和
s, i = 0, 1
for i in range(100):
if i % 3 == 0:
continue
else:
s += i
print(s)
i,sum=1,0
while i<=100:
if(i%3!=0):
sum+=i
i+=1
print(sum)
1.3.4 for循環(huán)
for 變量名 in 可迭代對(duì)象:
循環(huán)執(zhí)行的語(yǔ)句
for 循環(huán)一般用于迭代list劝篷、tuple這種可迭代對(duì)象的。也可以通過(guò)range()函數(shù)生成迭代器民宿。
person = {'name': '凌永琪', 'height': 160, 'salary': 100.0, 'weight': 50, 'sex': '女', 'lovies': ['看書', '跑步']}
# 從person中每一次迭代獲取的元素或內(nèi)容賦值給 k 變量娇妓。k變量名可任意的有效字符。
for k in person: # 字典對(duì)象迭代是它的所有的key
value = person.get(k)
# 判斷value是否為int類型的數(shù)值
# isinstance 和 type活鹰、 dir 三個(gè)函數(shù)都屬于自省函數(shù)
if isinstance(value, int):
print('找到了value為int類型的內(nèi)容', k, value)
【推導(dǎo)式】
列表的推導(dǎo)式: [ 變量名 for 變量名 in range(0, 10) 或 可迭代的對(duì)象 [條件表達(dá)式] ]
生成器的推導(dǎo)式:( 變量名 for 變量名 in range(0, 10) 或 可迭代的對(duì)象 [條件表達(dá)式] ) 哈恰,生成器是可迭代的對(duì)象。generator類型名华望, 它的結(jié)構(gòu)類似于棧蕊蝗, 只能被迭代一次。
# 練習(xí): 從ns列中提取出5的倍數(shù)的數(shù)值
ns = [9, 10, 20, 45]
[ n for n in ns if n % 5 == 0]
# 練習(xí): 隨機(jī)產(chǎn)生100個(gè)學(xué)生的Python課程的成績(jī), 成績(jī)的范圍是[0, 100]
import random
python_scores = [ random.randint(0, 100) for i in range(100) ]
print(python_scores)
# len(list|dict|tuple|str) 獲取指定類型對(duì)象的長(zhǎng)度赖舟, 用于list或str或tuple
print(len(python_scores))
【練習(xí)】元素位置互換問(wèn)題: 將”08,45,68,56,44”想變成”80,54,86,65,44”
>>> [item.strip()[::-1] for item in a.split(',')]
['80', '54', '86', '65', '44']
>>> ','.join([item.strip()[::-1] for item in a.split(',')])
'80,54,86,65,44'
【提示】選擇str.split(',') 以逗號(hào)分隔元素生成一個(gè)list列表蓬戚,再通過(guò)推導(dǎo)式和str的索引切片操作,將內(nèi)容互換宾抓,再通過(guò)','.join(可迭代對(duì)象)
將列表中的互換位置之后的元素以逗號(hào)的方式拼接成一個(gè)字符串子漩。
參考以下的代碼:
>>> s = '2, 22, 78, 61, 21'
>>> s.split(',')
['2', ' 22', ' 78', ' 61', ' 21']
>>> [ item.strip()[::-1] for item in s.split(',') ]
['2', '22', '87', '16', '12']
>>> ','.join([ item.strip()[::-1] for item in s.split(',') ])
'2,22,87,16,12'
>>>
str.strip()函數(shù)是刪除字符串的兩端的空白,類似于java中String對(duì)象的trim()函數(shù)石洗。
>>> g1 = (i for i in range(0, 10))
>>> g1
<generator object <genexpr> at 0x7fd3034b2a98>
>>> list(g1)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(g1)
[]
【作業(yè)】獲取str對(duì)象的方法幢泼,自我嘗試使用str對(duì)象的相關(guān)方法(5到10個(gè)方法)。
# dir('abc')
# help(str.strip)
>>> dir(str)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> 'hellodisen'.capitalize()
'Hellodisen'
>>> 'hellodisen'.title()
'Hellodisen'
>>> 'redapple'.title()
'Redapple'
>>> 'red,apple'.title()
'Red,Apple'
>>> 'red,apple'.capitalize()
'Red,apple'
>>> 'abc.txt'.endswith('.txt')
True
>>> files = ['a.txt', 'b.png', 'c.txt']
>>> [filename for filename in files if filename.endswith('.txt')]
['a.txt', 'c.txt']
>>> 'a.txt'.replace('a', 'day02')
'day02.txt'
>>> 'hi,disen'.find('i')
1
>>> 'hi,disen'.rfind('i')
4
>>> 'hi,disen'.find('c')
-1
>>> 'hi,disen'.index('i')
1
>>> 'hi,disen'.rindex('i')
4
>>> 'hi,disen'.index('c')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
>>>
1.4 函數(shù)定義與裝飾器
函數(shù)作用: 封裝復(fù)雜的功能代碼讲衫,提高代碼的重復(fù)使用率缕棵。
1.4.1 函數(shù)的定義
def 函數(shù)名([參數(shù)列表]):
函數(shù)功能
[return 函數(shù)結(jié)果]
# 定義計(jì)算某個(gè)數(shù)值內(nèi)的和
def sum_n(n):
s, i = 0, 1
while i <= n:
s += i
i += 1
return s
# 列出指定目錄下的文件, 需要使用os模塊
import os
def ls_files(dir_path):
files = os.listdir(dir_path) # 返回一個(gè)文件列表
for filename in files:
# os.path.join(dir, filename) 將文件名和目錄拼接成文件的完整路徑
print( os.path.join(dir_path, filename) )
# 沒(méi)有return 語(yǔ)句,則默認(rèn)返回None
>>> os.listdir('./sql')
['w18.sql', '4.sql', '5.sql', '2.sql', '3.sql', '1.sql', 'w8.sql']
>>> os.getcwd()
'/Users/apple'
>>> ls_files('./sql')
./sql/w18.sql
./sql/4.sql
./sql/5.sql
./sql/2.sql
./sql/3.sql
./sql/1.sql
./sql/w8.sql
./sql
指當(dāng)前目錄下的sql子目錄(相對(duì)路徑)涉兽。如果Window指定絕對(duì)路徑r'd:\sql'
招驴。
1.4.2 函數(shù)的參數(shù)
形參: 定義函數(shù)時(shí)聲明的參數(shù)
實(shí)參: 調(diào)用函數(shù)時(shí),傳遞的參數(shù)(值枷畏, 引用)
值傳參:標(biāo)識(shí)符(變量)指向的內(nèi)容在常量池(內(nèi)存區(qū))别厘, 如 a=100, sum_n(a)
引用傳參:標(biāo)識(shí)符指向的內(nèi)容在堆內(nèi)存中, 如 l=[1, 2, 3], sum_list(l)
在調(diào)用函數(shù)時(shí),可以按參數(shù)的位置從左到右依次傳參(位置傳值)拥诡, 還可以指定參數(shù)名傳參(關(guān)鍵參數(shù)傳值)触趴。
def sum_ns(n1, n2, n3, n4):
print(n1, n2, n3, n4)
return n1+n2+n3+n4
sum_ns(1, 2, 3, 4) # 位置傳值
sum_ns(4, n4=1, n2=10, n3=90) # 關(guān)鍵參數(shù)傳值,從使用關(guān)鍵參數(shù)方式傳值的位置開(kāi)始,后面所有的參數(shù)必須是關(guān)鍵參數(shù)的方式渴肉。
在聲明或定義函數(shù)時(shí)冗懦,可以指定形參的默認(rèn)值
def sum_ns(n1, n2, n3=10, n4=100):
print(n1, n2, n3, n4)
return n1+n2+n3+n4
sum_ns(1, 2) # 傳參時(shí),帶有默認(rèn)值的參數(shù)宾娜,可以不用傳值批狐。
sum_ns(1,2, 1000, 10000) # 帶有默認(rèn)值的參數(shù),也可以傳值
聲明形參時(shí)前塔,可以使用不定長(zhǎng)參數(shù)
- 位置參數(shù)
*args
, args是元組類型 - 關(guān)鍵參數(shù)
**kwargs
嚣艇, kwargs是字典類型
def sum_ns(*args):
print(args)
return sum(args) # python內(nèi)置求和函數(shù) sum
sum_ns(1,2) # 可以只傳2個(gè)
sum_ns(1,2,3) # 可以只傳3個(gè), 也可以傳更多的參數(shù)
# 通過(guò)字典對(duì)象的數(shù)據(jù)生成insert 插入的SQL語(yǔ)句
def save(table_name, **data):
# insert into 表名(列名1华弓, 列名2,...) values(列值1食零, 列值2, ...)
# str字符串的格式化(%寂屏、format)
sql = 'insert into %s(%s) values(%s)'
fields = ','.join(data.keys())
values = []
for k in data:
v = data[k]
# 判斷數(shù)據(jù)類型贰谣, 如果字符類型(varchar),在mysql數(shù)據(jù)庫(kù)中迁霎,加''單引號(hào)
if isinstance(v, int) or isinstance(v, float):
values.append("%s" % v) # "1"
else:
values.append("'%s'" % v) # "'disen'"
values = ','.join(values)
full_sql = sql % (table_name, fields, values)
print(full_sql)
# pass # pass 表示省略代碼(保留)吱抚,保持函數(shù)結(jié)構(gòu)的完整性
>>> '%s' % 'disen'
'disen'
>>> 'hi, %s' % 'jack'
'hi, jack'
>>> 'hi, %s, city at %s' % ('disen', '西安')
'hi, disen, city at 西安'
>>> 'hi, %(name)s,city at %(city)s' % {'name': 'jack', 'city': '西安'}
'hi, jack,city at 西安'
>>>
save('tb_user', id=1, name='disen', age=20, salary=1000, years=10, height=180, city='西安', address="立人科技")
# insert into tb_user(id,name,age,salary,years,height,city,address)
# values (1, 'disen',20, 1000,10,180,'西安', '立人科技')
save('tb_store', id=1, name='disen愛(ài)心水果店', day_open='08:00', day_close='18:00')
# insert into tb_store(id,name,day_open, day_close)
# values (1, 'disen愛(ài)心水果店', '08:00', '18:00')
1.4.3 函數(shù)的生成器
# next在Python中存在一個(gè)內(nèi)置的函數(shù)
def _next_(arr):
for n in arr:
yield n # 將當(dāng)前的函數(shù)轉(zhuǎn)成生成器,產(chǎn)生一個(gè)可迭代的元素考廉,好處:節(jié)省內(nèi)存
生成器對(duì)象可以被for循環(huán)迭代秘豹, 也可以通過(guò)next(generator)獲取生成器產(chǎn)生的元素,如果生成器中的元素不產(chǎn)出了昌粤,但強(qiáng)行執(zhí)行next()函數(shù)時(shí)既绕,則拋出StopIteration異常錯(cuò)誤。
>>> ne = _next_([1,2,3,4])
>>> for n in ne:
... print(n)
...
1
2
3
4
>>> for n in ne:
... print(n)
...
>>> ne = _next_([1,2,3,4])
>>> next(ne)
1
>>> next(ne)
2
>>> next(ne)
3
>>> next(ne)
4
>>> next(ne)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
1.4.4 函數(shù)裝飾器
裝飾器是一種設(shè)計(jì)模式(23種)思想涮坐, 主要解決擴(kuò)展現(xiàn)有代碼(程序)的功能凄贩,不會(huì)影響現(xiàn)有的功能。
import time
# 聲明裝飾器函數(shù),如實(shí)現(xiàn)被裝飾函數(shù)的運(yùn)行時(shí)間
def runtime(func):
def wrapper(*args, **kwargs):
# print('--擴(kuò)展功能--')
start_time = time.time() # 獲取當(dāng)前的時(shí)間戳
ret = func(*args, **kwargs)
end_time = time.time()
print('耗時(shí)(秒)', round(end_time - start_time, 4))
return ret
return wrapper
# 使用裝飾器函數(shù)
# 實(shí)現(xiàn)n的數(shù)值以內(nèi)的所有數(shù)的和袱讹,e表示某個(gè)數(shù)陪數(shù)不參與計(jì)算
@runtime
def sum_n(n=100, e=None):
s, i = 0, 1
while i<=n:
if e is not None:
if i % e != 0:
s += i
else:
s += i
i += 1
# 每一次循環(huán)疲扎,增加一點(diǎn)休眼時(shí)間
time.sleep(0.01)
return s
在Python中,某一個(gè)函數(shù)上方使用裝飾器函數(shù)捷雕,則會(huì)按照閉包流程產(chǎn)生一個(gè)閉包函數(shù)椒丧,當(dāng)調(diào)用被裝飾的函數(shù)時(shí),實(shí)際上調(diào)用是這個(gè)閉包函數(shù)(產(chǎn)生條件:內(nèi)部函數(shù)持有外部函數(shù)的引用)非区。
1.5 類與對(duì)象
類: 由多個(gè)具有相同的屬性(特征)和方法(行為)的對(duì)象抽象出來(lái)的類型
對(duì)象: 由類實(shí)例化出來(lái)的具體的事物瓜挽。
1.5.1 定義類
# 定義學(xué)生類
# Python中所有類的父類(基類)都是object類
class Student(object):
# 定義類的初始化實(shí)例屬性的方法
def __init__(self, sn, name, age, sex):
# self 當(dāng)前類的實(shí)例對(duì)象引用, 類似于java中類方法中this
self.sn = sn # 將方法的參數(shù)賦值給實(shí)例的屬性(動(dòng)態(tài))
self.name = name
self.age = age
self.sex = sex
self.cources = []
# 所有類的實(shí)例方法征绸,第一個(gè)參數(shù)self表示當(dāng)前的實(shí)例對(duì)象
def select_cource(self, cource_name):
self.cources.append(cource_name)
# 取消選擇課程
def unselect_cource(self, cname):
# 判斷 cname課程名是否存在于當(dāng)前已選擇的課程中
if cname in self.cources:
self.cources.remove(cname)
else:
print('你取消的課程 %s 不存在于已選擇的課程列表中' % cname)
def show_info(self):
print(self.sn, self.name, self.age, self.sex, self.cources)
1.5.2 類的實(shí)例化
s1 = Student('01', '婷婷', 21, '女') # 先創(chuàng)建類的實(shí)例久橙,再調(diào)用__init__()方法
s1.select_cource('Python')
s1.select_cource('Java')
s1.select_cource('H5')
s1.show_info() # 調(diào)用對(duì)象方法時(shí),無(wú)須考慮形參中的self參數(shù)管怠,因?yàn)榉椒ㄓ蓪?duì)象調(diào)用的淆衷,當(dāng)前對(duì)象自動(dòng)傳入到self
1.6 包與模塊
包(package 文件目錄)和模塊(python腳本)屬于項(xiàng)目工程的概念,如果一項(xiàng)工程非常龐大渤弛,可以借助包或模塊拆分或細(xì)化軟件工程祝拯,便于多人協(xié)作開(kāi)發(fā)和代碼維護(hù)。
包: 文件目錄+__init__.py
, __init__.py
文件初始化當(dāng)前的package包, 在此腳本聲明的變量或編寫的函數(shù)都屬于單例模式佳头,即無(wú)論包使用(導(dǎo)入)多少次鹰贵,初始化腳本(__init__.py
)只會(huì)執(zhí)行一次。
導(dǎo)包: 導(dǎo)入 import 包名(文件目錄名)
模塊: 某一個(gè)包(package)下的一個(gè)python腳本康嘉。
zzserver(project)
|--db (package)
|-- __init__.py
|-- user_db.py
|-- order_db.py
|-- goods_db.py
|--service
|-- __init__.py
|-- user_service.py
|--utils
|-- __init__.py
|--view
|-- __init__.py
|--pay
|-- __init__.py
|--order
|-- __init__.py
# user_db.py內(nèi)容
class UserDB:
pass
class User:
pass
# order_db.py內(nèi)容
class OrderDB:
pass
# 在 user_service.py腳本中導(dǎo)入db包下的user_db.py中 UserDB類
from db.user_db import UserDB # 同一個(gè)模塊的導(dǎo)入場(chǎng)景
from db.user_db import User
from db.order_db import OrderDB
1.7 with上下文與異常
在Python中碉输,所有的對(duì)象都可以托管給上下文管理器,使用 with關(guān)鍵字亭珍,語(yǔ)法如下:
with obj [as 標(biāo)識(shí)符]:
# 進(jìn)入上下文
# 功能
pass
# 退出上下文
【注意】obj托管上下文之前敷钾,obj所屬的類必須 實(shí)現(xiàn)__enter__
和__exit__
兩個(gè)方法,如果沒(méi)有實(shí)現(xiàn)肄梨,則拋出異常阻荒。
上下文管理器作用: 確定程序正常執(zhí)行,在代碼執(zhí)行之前众羡,分配資源侨赡;在執(zhí)行完成后,可以合理地回收資源纱控。
當(dāng)對(duì)象obj進(jìn)入上下文時(shí)辆毡,調(diào)用obj.__enter__
函數(shù), 當(dāng)退出上下文時(shí),調(diào)用obj.__exit__
函數(shù)甜害。
class DB:
def __enter__(self):
print('--進(jìn)入上下文--')
self.conn = '已連接'
return self.conn # 可以沒(méi)有返回
def __exit__(self, except_type, msg, tb):
print('--退出上下文--')
self.conn = None
if except_type: # 存在異常錯(cuò)誤
print('存在異常', msg)
return True # True表示如果出現(xiàn)的異常舶掖,則內(nèi)部消化; False 表示如果出現(xiàn)異常尔店,則由外部程序處理眨攘。
db = DB()
with db as c: # as 指定標(biāo)識(shí)符來(lái)接收enter函數(shù)返回結(jié)果或數(shù)據(jù)
print(c)
print(10/0)
print('--gogogo---')
print(db.conn) # 退出上下文時(shí),db.conn為None
1.8 文件操作
Python中文件讀寫操作之前嚣州,必須先打開(kāi)文件鲫售,使用open()函數(shù)。
open(file, mode='r', buffering=-1, encoding=None)
- file表示文件的路徑(相對(duì)路徑或絕對(duì)路徑)
- mode 文件打開(kāi)模式该肴,如果文件準(zhǔn)備寫操作情竹,則mode應(yīng)該寫相對(duì)應(yīng)字符,如'w'或'a'匀哄、'r+'秦效、'w+'
- w 只寫文本
- r 只讀文本
- rw 讀寫文本
- r+ 讀寫文本, 如果文件不存在涎嚼,則拋出異常
- w+讀寫文本阱州,如果文件不存在,則會(huì)自動(dòng)創(chuàng)建法梯; 另外苔货,原內(nèi)容則會(huì)被重寫。
- a 追加文件內(nèi)容,在文件的末尾行新增內(nèi)容夜惭, 原內(nèi)容還存在姻灶。
- r+b 讀寫字節(jié)數(shù)據(jù)
- w+b 讀寫字節(jié)數(shù)據(jù)
- ab 追加字節(jié)數(shù)據(jù)
- buffering 指定讀寫數(shù)據(jù)的緩存大小,默認(rèn)為-1滥嘴,表示全部寫入或全部讀取木蹬。
- encoding 表示讀取文本數(shù)據(jù)的字符集至耻,如果是b的字節(jié)模式若皱,則不能設(shè)置encoding,否則拋出異常尘颓。
# 編寫python的打印helloworld腳本,腳本名為a.py
stream = open('a.py', 'w', encoding='utf-8') # 以只寫的模式打開(kāi)文件走触,返回一個(gè)文件流對(duì)象
stream.write("print('hello, world')")
stream.close()
stream = open('a.py', 'r', encoding='utf-8')
stream.read()
stream = open('a.py', 'w+', encoding='utf-8')
stream.write("print('hello, world')") # 寫入之后,文件句柄(指針)指向文件末尾的位置
stream.seek(0) # 移動(dòng)文件句柄到每一個(gè)字符的前面
stream.read()
文件流stream可以在with 中使用:
with open('a.py', 'w+', encoding='utf-8') as stream:
stream.write("print('hello, world')") # 寫入之后疤苹,文件句柄(指針)指向文件末尾的位置
stream.seek(0) # 移動(dòng)文件句柄到每一個(gè)字符的前面
stream.read()