Day03的課程要點(diǎn)記錄
詳細(xì)教程地址:金角大王 - Day3 Python基礎(chǔ)3 | 金角大王 - Day2 Python基礎(chǔ)2 | 銀角大王 - Python基礎(chǔ)(二)
一、集合的使用
集合是一個(gè)無(wú)序的,不重復(fù)的數(shù)據(jù)組合,它的主要作用如下:
- 去重,把一個(gè)列表變成集合,自動(dòng)去重
- 關(guān)系測(cè)試,測(cè)試兩組數(shù)據(jù)之前的交集、差集、并集等關(guān)系
1.1 常用操作
a = {11, 22, 33, 44}
s = set([3, 5, 9, 10]) #創(chuàng)建一個(gè)數(shù)值集合
t = set('Hello') #創(chuàng)建一個(gè)唯一字符的集合
a = t | s # t 和 s 的并集
b = t & s # t 和 s 的交集
c = t - s # 求差集(項(xiàng)在t中,但不在s中)
d = t ^ s # 對(duì)稱(chēng)差集(項(xiàng)在t或s中,但不會(huì)同時(shí)出現(xiàn)在二者中)
1.2 基本操作
-
s.intersection(t)
,s & t,交集,返回一個(gè)新的 set 包含 s 和 t 中的公共元素
>>> s.intersection(t)
set()
-
s.union(t)
,s | t,并集,放回一個(gè)新的 set 包含 s 和 t 中的每一個(gè)元素
>>> s.union(t)
{'e', 3, 'l', 5, 'H', 9, 10, 'o'}
-
s.difference(t)
,s - t,差集,返回一個(gè)新的 set 包含 s 中有但是 t 中沒(méi)有的元素
>>> s.difference(t)
{9, 10, 3, 5}
-
s.issubset(t)
,s <= t,子集,測(cè)試 s 中的每一個(gè)元素是否都在 t 中
>>> s.issubset(t)
False
-
s.issuperset(t)
,s >= t,父集,測(cè)試 t 中的每一個(gè)元素是否都在 s 中
>>> s.issuperset(t)
False
-
s.symmetric_difference()
,s ^ t,對(duì)稱(chēng)差集,返回一個(gè)新的 set 包含 s 和 t 中不重復(fù)的元素
>>> s.symmetric_difference(t)
{'e', 'l', 'H', 3, 5, 9, 10, 'o'}
s.copy()
,返回 set “s”的一個(gè)淺復(fù)制s.isdisjoint(t)
,零交叉測(cè)試,如果兩個(gè)集合中零交叉,則返回True
>>> s.isdisjoint(t)
True
1.3 增刪改查
1.3.1 增加元素
-
t.add('a')
向集合內(nèi)添加一項(xiàng)元素
>>> t.add('a')
>>> t
{'o', 'e', 'l', 'H', 'a'}
-
s.update([111, 222, 333])
向集合內(nèi)添加多項(xiàng)元素
>>> s.update([111, 222, 333])
>>> s
{3, 5, 9, 10, 333, 111, 222}
1.3.2 刪除元素
-
s.pop()
隨機(jī)刪除 s 中的一個(gè)元素,并返回
>>> s.pop()
3
-
t.remove('a')
刪除 t 中的元素 a
>>> t.remove('a')
>>> t
{'o', 'e', 'l', 'H'}
-
s.discard()
刪除 s 中的一個(gè)指定元素,如果沒(méi)有此元素,不報(bào)錯(cuò)
>>> s.discard(333)
>>> s
{5, 9, 10, 111, 222}
>>> s.discard(999)
>>> s
{5, 9, 10, 111, 222}
1.3.4 其他
len(s)
set 的長(zhǎng)度x in s 測(cè)試 x 是否是 s 的成員
x not in s 測(cè)試 x 是否不是 s 的成員
set集合練習(xí)題
old_dict = {
'#1': 8,
'#2': 4,
'#4': 2
}
new_dict ={
'#1': 4,
'#2': 4,
'#3': 2
}
需求
- 應(yīng)該刪除哪幾個(gè)槽位?
- 應(yīng)該更新哪幾個(gè)槽位?
- 應(yīng)該增加哪幾個(gè)槽位?
實(shí)現(xiàn)代碼:
old_set = set(old_dict.keys())
new_set = set(new_dict.keys())
del_set = old_set.difference(new_set) # 應(yīng)該刪除old中有new中無(wú)的差集
update_set = old_set.intersection(new_set) # 應(yīng)該更新old和new的交集
add_set = new_set.difference(old_set) # 應(yīng)該增加new中有old中無(wú)的差集
print(del_set)
print(update_set)
print(add_set)
二、文件操作
對(duì)文件操作流程:
- 打開(kāi)文件,得到文件句柄并賦值給一個(gè)變量
- 通過(guò)句柄對(duì)文件進(jìn)行操作
- 關(guān)閉文件
2.1 基本操作 - 讀、寫(xiě)、追加
f = open('lyrics') # 打開(kāi)文件
first_line = f.readline()
print('first line:',first_line) # 讀一行
print('我是分隔線(xiàn)'.center(50,'-'))
data = f.read() # 讀取剩下的所有內(nèi)容,文件大時(shí)不要用
print(data) # 打印文件
f.close() # 關(guān)閉文件
打開(kāi)文件的模式有:
- r,只讀模式(默認(rèn))。
- w,只寫(xiě)模式。【不可讀;不存在則創(chuàng)建;存在則刪除內(nèi)容;】
- a,追加模式。【可讀; 不存在則創(chuàng)建;存在則只追加內(nèi)容;】
"+" 表示可以同時(shí)讀寫(xiě)某個(gè)文件
- r+,可讀寫(xiě)文件。【可讀;可追加寫(xiě)】
- w+,寫(xiě)讀
- a+,同a 【追加讀】
"U"表示在讀取時(shí),可以將 \r \n \r\n自動(dòng)轉(zhuǎn)換成 \n (與 r 或 r+ 模式同使用)
- rU
- r+U
"b"表示處理二進(jìn)制文件(如:FTP發(fā)送上傳ISO鏡像文件,linux可忽略,windows處理二進(jìn)制文件時(shí)需標(biāo)注)
- rb 網(wǎng)絡(luò)傳輸情況下
- wb
- ab
2.2 循環(huán)讀取文件內(nèi)容
- 差方法
# 讀取到第9行時(shí),打印分割線(xiàn)
for index,line in enumerate(f.readlines())
if index == 9:
print("我是分隔線(xiàn)".center(20, '-'))
continue
print(line.strip())
- 好方法
count = 0
for line in f:
if count == 9:
print("我是分隔線(xiàn)".center(20, '-'))
count += 1
continue
print(line.strip())
count += 1
2.3 其他方法
f.tell()
獲取當(dāng)前光標(biāo)位置,以及f.seek()
移動(dòng)光標(biāo)位置
print(f.tell()) # 獲取當(dāng)前光標(biāo)位置。 (0)
print(f.readline()) # 打印第一行
print(f.readline()) # 打印第二行
print(f.tell()) # 獲取當(dāng)前光標(biāo)位置。 (140)
print(f.seek(0)) # 光標(biāo)移回至起始處
print(f.readline()) # 打印第一行
f.enconding()
當(dāng)前文件的編碼
f.fileno()
返回文件在內(nèi)存中的編號(hào)
f.name()
當(dāng)前文件的名字
f.seekable()
判斷文件光標(biāo)是否可移
f.readable()
判斷文件是否可讀
f.writable()
判斷文件是否可寫(xiě)
f.truncate()
從文件起始截?cái)嗟街付〝?shù)(不填則清空)
f. flush()
將內(nèi)存中暫存的內(nèi)容刷新寫(xiě)入硬盤(pán)
命令行進(jìn)度條實(shí)現(xiàn)方式
import sys, time
for i in range(100):
sys.stdout.write('#')
sys.stdout.flush()
time.sleep(0.1) # 每打印一個(gè)sleep0.1秒
2.4 文件的修改
將文件中某一行內(nèi)的文字進(jìn)行部分替換
# 將文本中全部的"我"替換為"你"
f = open('Yesterday2', 'r', encoding='utf-8')
f_new = open('Yesterday2.bak', 'w', encoding='utf-8')
for line in f:
if '我' in line:
line = line.replace('我', '你')
f_new.write(line)
f.close()
f_new.close()
2.5 with
語(yǔ)句
為了避免打開(kāi)文件后忘記關(guān)閉,可以通過(guò)管理上下文,即:
with open('log','r') as f:
...
如此方式,當(dāng)with代碼塊執(zhí)行完畢時(shí),內(nèi)部會(huì)自動(dòng)關(guān)閉并釋放文件資源。
在Python 2.7 后,with又支持同時(shí)對(duì)多個(gè)文件的上下文進(jìn)行管理,即:
with open('log1') as obj1, open('log2') as obj2:
pass
課堂練習(xí)
程序1:實(shí)現(xiàn)簡(jiǎn)單的shell sed替換功能
import sys
find_str = sys.argv[1]
replace_str = sys.argv[1]
with open('Yesterday2', 'r', encoding='utf-8')as f,\
open('Yesterday3', 'w', encoding='utf-8') as f_new:
for line in f:
if find_str in line:
line = line.replace(find_str, replace_str)
f_new.write(line)
三、字符轉(zhuǎn)編碼操作
詳細(xì)文章:py編碼終極版 | Strings - Dive into Python3
Ascii碼:每個(gè)字符存1個(gè)字節(jié)
Unicode:每個(gè)字符存2個(gè)字節(jié)
utf-8:英文用1個(gè),其他用3個(gè)字節(jié)
所有轉(zhuǎn)換動(dòng)作都需要先decode為Unicode,再encode為相應(yīng)編碼
在字符串之前加u,默認(rèn)為其是Unicode,可直接encode
練習(xí):將字符按順序轉(zhuǎn)換編碼,gb2312 -> utf-8 -> gbk。
Python2
import sys
print(sys.getdefaultencoding()) # 獲取默認(rèn)編碼格式
s = '學(xué)習(xí)學(xué)習(xí)再學(xué)習(xí)'
s_gb = s.decode('uft-8').encode('gb2312') # utf-8 -> gb2312
s_gb_utf8 = s_gb.decode('gb2312').encode('utf-8') # gb2312 -> utf-8
s_gb_utf8_gbk = s_gb_utf8.decode('utf-8').encode(gbk) # utf-8 -> gbk
print(s_gb.decode('gb2312'))
print(s_gb_utf8.decode('utf-8'))
print(s_gb_utf8_gbk.decode('gbk'))
Python3: 3中encode同時(shí)會(huì)轉(zhuǎn)換為bytes,顯示字符串需要decode為unicode
import sys
print(sys.getdefaultencoding()) # 獲取默認(rèn)編碼格式
s = '學(xué)習(xí)學(xué)習(xí)再學(xué)習(xí)' # py3_default = unicode
s_gb = s.encode('gb2312') # unicode -> gb2312
s_gb_utf8 = s_gb.decode('gb2312').encode('utf-8') # gb2312 -> utf-8
s_gb_utf8_gbk = s_gb_utf8.decode('utf-8').encode('gbk') # utf-8 -> gbk
print(s_gb.decode('gb2312'))
print(s_gb_utf8.decode('utf-8'))
print(s_gb_utf8_gbk.decode('gbk'))
四、函數(shù)
4.1 函數(shù)是什么?
函數(shù)是指將一組語(yǔ)句的集合通過(guò)一個(gè)名字(函數(shù)名)封裝起來(lái),要想執(zhí)行這個(gè)函數(shù),只需調(diào)用其函數(shù)名。
4.2 基本語(yǔ)法及特性
4.2.1 語(yǔ)法定義
def sayhi(): #函數(shù)名
print("Hello, I'm nobody!")
sayhi() #調(diào)用函數(shù)
帶參數(shù)
# 下面這段代碼
a,b = 5,8
c = a**b
print(c)
# 改成用函數(shù)寫(xiě)
def calc(x,y):
res = x**y
return res # 返回函數(shù)執(zhí)行結(jié)果
c = calc(a,b) # 結(jié)果賦值給c變量
print(c)
4.2.2 特性:
- 減少重復(fù)代碼
- 使程序變得可擴(kuò)展
- 使程序變得易維護(hù)
4.3 返回值
用return
語(yǔ)句返回函數(shù)的執(zhí)行結(jié)果。
注意:
- 函數(shù)在執(zhí)行過(guò)程中只要遇到
return
語(yǔ)句,就會(huì)停止執(zhí)行并返回結(jié)果。所以可以理解為return
語(yǔ)句代表著函數(shù)的結(jié)束。 - 如果未在函數(shù)中指定
return
,那這個(gè)函數(shù)的返回值為None
。
4.4 函數(shù)參數(shù)
4.4.1 形參與實(shí)參
形參:變量只有在被調(diào)用時(shí)才分配內(nèi)存單元,在調(diào)用結(jié)束時(shí),即刻釋放所分配的內(nèi)存單元。因此,形參只在函數(shù)內(nèi)部有效。函數(shù)調(diào)用結(jié)束返回主調(diào)用函數(shù)后則不能再使用該形參變量
實(shí)參:可以是常量、變量、表達(dá)式、函數(shù)等,無(wú)論實(shí)參是何種類(lèi)型的量,在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須有確定的值,以便把這些值傳送給形參。因此應(yīng)預(yù)先用賦值,輸入等辦法使參數(shù)獲得確定值
# 改成用函數(shù)寫(xiě)
def calc(x,y):
res = x**y
return res
c = calc(a,b)
print(c)
4.4.2 位置參數(shù)
按順序給函數(shù)傳參數(shù)
def test(x,y,z):
print(x)
print(y)
print(z)
test(1, 2, 3)
4.4.3 關(guān)鍵參數(shù)
正常情況下,給函數(shù)傳參數(shù)要按順序,不想按順序就可以用關(guān)鍵參數(shù),只需指定參數(shù)名即可。但記住一個(gè)要求就是,關(guān)鍵參數(shù)必須放在位置參數(shù)之后。
def test(x,y,z):
print(x)
print(y)
print(z)
test(3, z=6, y=9)
4.4.4 默認(rèn)參數(shù)
在寫(xiě)形參時(shí)直接給形參定義的一個(gè)值。
特點(diǎn):調(diào)用函數(shù)的時(shí)候,默認(rèn)函數(shù)非必須傳遞。
用途:
- 默認(rèn)安裝值
- 默認(rèn)端口號(hào)
def test(x,y=2):
print(x)
print(y)
test(1)
test(1,10)
4.4.5 非固定參數(shù)
*args
- 把多傳入的位置參數(shù)變成一個(gè)元組形式。
def stu_register(name,age,*args): # *args 會(huì)把多傳入的參數(shù)變成一個(gè)元組形式
print(name,age,args)
stu_register("Alex",22)
#輸出
#Alex 22 () # 后面這個(gè)()就是args,只是因?yàn)闆](méi)傳值,所以為空
stu_register("Jack",32,"CN","Python")
#輸出
# Jack 32 ('CN', 'Python') # 多傳入的參數(shù)為元組形式
**kwargs
- 將多個(gè)關(guān)鍵字參數(shù)寫(xiě)為字典
def stu_register(name,age,*args,**kwargs): # *kwargs 會(huì)把多傳入的參數(shù)變成一個(gè)dict形式
print(name,age,args,kwargs)
stu_register("Alex",22)
#輸出
#Alex 22 () {}#后面這個(gè){}就是kwargs,只是因?yàn)闆](méi)傳值,所以為空
stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")
#輸出
# Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}
4.5 全局變量與局部變量
在子程序中定義的變量稱(chēng)為局部變量,在程序的一開(kāi)始定義的變量稱(chēng)為全局變量。
全局變量作用域是整個(gè)程序,局部變量作用域是定義該變量的子程序。
當(dāng)全局變量與局部變量同名時(shí):
在定義局部變量的子程序內(nèi),局部變量起作用;在其它地方全局變量起作用。
name = 'Will'
def change_name(name):
print("before change:", name)
name = 'William'
print('after name', name)
change_name(name)
print(name)
想在函數(shù)內(nèi)改變?nèi)肿兞恳嚷暶鳎?strong>可實(shí)現(xiàn),但盡量不要用,出錯(cuò)后調(diào)試難度幾何級(jí)提升)
name = 'Will'
school = 'Hometown'
def change_name(name):
global school
print("before change:", name)
name = 'William'
school = 'University'
print('after name', name)
change_name(name)
print(name,school)
五、遞歸
在函數(shù)內(nèi)部,可以調(diào)用其他函數(shù)。如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身,這個(gè)函數(shù)就是遞歸函數(shù)。
遞歸的特性:
- 遞歸必須有一個(gè)明確的結(jié)束條件
- 每次進(jìn)入更深一層遞歸時(shí),問(wèn)題規(guī)模相比上次遞歸都應(yīng)有所減少
- 遞歸效率不高,遞歸層次過(guò)多會(huì)導(dǎo)致棧溢出(在計(jì)算機(jī)中,函數(shù)調(diào)用是通過(guò)棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,每當(dāng)進(jìn)入一個(gè)函數(shù)調(diào)用,棧就會(huì)加一層棧幀,每當(dāng)函數(shù)返回,棧就會(huì)減一層棧幀。由于棧的大小不是無(wú)限的,所以,遞歸調(diào)用的次數(shù)過(guò)多,會(huì)導(dǎo)致棧溢出)
def calc(n):
print(n)
if int(n) > 0:
return calc(int(n/2))
calc(10)
六、函數(shù)式編程介紹
函數(shù)是Python內(nèi)建支持的一種封裝,我們通過(guò)把大段代碼拆成函數(shù),通過(guò)一層一層的函數(shù)調(diào)用,就可以把復(fù)雜任務(wù)分解成簡(jiǎn)單的任務(wù),這種分解可以稱(chēng)之為面向過(guò)程的程序設(shè)計(jì)。函數(shù)就是面向過(guò)程的程序設(shè)計(jì)的基本單元。
函數(shù)式編程中的函數(shù)這個(gè)術(shù)語(yǔ)不是指計(jì)算機(jī)中的函數(shù)(實(shí)際上是Subroutine),而是指數(shù)學(xué)中的函數(shù),即自變量的映射。也就是說(shuō)一個(gè)函數(shù)的值僅決定于函數(shù)參數(shù)的值,不依賴(lài)其他狀態(tài)。比如sqrt(x)函數(shù)計(jì)算x的平方根,只要x不變,不論什么時(shí)候調(diào)用,調(diào)用幾次,值都是不變的。
Python對(duì)函數(shù)式編程提供部分支持。由于Python允許使用變量,因此,Python不是純函數(shù)式編程語(yǔ)言。
6.1 定義
簡(jiǎn)單說(shuō),"函數(shù)式編程"是一種"編程范式"(programming paradigm),也就是如何編寫(xiě)程序的方法論。主要思想是把運(yùn)算過(guò)程盡量寫(xiě)成一系列嵌套的函數(shù)調(diào)用。
一個(gè)數(shù)學(xué)表達(dá)式:(1 + 2) * 3 - 4
傳統(tǒng)的過(guò)程式編程
var a = 1 + 2;
var b = a * 3;
var c = b - 4;
函數(shù)式編程要求使用函數(shù),可以把運(yùn)算過(guò)程定義為不同的函數(shù),寫(xiě)成下面這樣:
var result = subtract(multiply(add(1, 2), 3), 4);
再演進(jìn)一下,可以變成這樣
add(1,2).multiply(3).subtract(4)
這基本就是自然語(yǔ)言的表達(dá)了。再看下面的代碼,應(yīng)該一眼就能明白它的意思:
merge([1,2],[3,4]).sort().search("2")
因此,函數(shù)式編程的代碼更容易理解。
但要想學(xué)好函數(shù)式編程,不要用Python,用Erlang,Haskell。
七、高階函數(shù)
變量可以指向函數(shù),函數(shù)的參數(shù)能接收變量。
而一個(gè)函數(shù)就可以接收另一個(gè)函數(shù)作為參數(shù),這種函數(shù)就稱(chēng)之為高階函數(shù)。
def add(a, b, f):
return f(a)+f(b)
res = add(3, 6, abs)
print(res)
八、作業(yè)
將輸入的字符串轉(zhuǎn)為字典的方法:b = eval(b)
| json
第3周作業(yè):day3 作業(yè)詳細(xì)
HAproxy配置文件操作(配置文件參考):
- 根據(jù)用戶(hù)輸入輸出對(duì)應(yīng)的backend下的server信息
- 可添加backend 和sever信息
- 可修改backend 和sever信息
- 可刪除backend 和sever信息
- 操作配置文件前進(jìn)行備份
- 添加server信息時(shí),如果ip已經(jīng)存在則修改;如果backend不存在則創(chuàng)建;若信息與已有信息重復(fù)則不操作