我的python學習之路-基礎3
本文內容:
- 檔案操作
- 函式
- 高階函式
- locals() 和 globals()
- 迭代器
- 高階函式
一 .檔案操作
對檔案操作流程
- 開啟檔案,得到檔案控制代碼並賦值給一個變數
- 通過控制代碼對檔案進行操作
- 關閉檔案
檔案內容可以寫入:1.位元組流 2.字串
1.基本操作
# 1.開啟檔案 fp = open("lianxi.txt",mode="w",encoding="utf-8") # 2.寫入檔案 fp.write("把大象塞進去") # 3.關閉檔案 fp.close()
# 1.開啟檔案 fp = open("lianxi.txt",mode="r",encoding="utf-8") # 2.讀取檔案 res = fp.read() # 3.關閉檔案 fp.close() print(res)
2.位元組流操作
二進位制位元組流的應用場景: 在資料傳輸或者在資料儲存時,使用的一種資料格式;
多個字元放在一起叫做字串,多個位元組放在一起叫做位元組流;
將字串和位元組流(Bytes流)型別進行轉換 (引數寫成轉化的字元編碼格式)
encode() 編碼 :將字串轉化為位元組流(Bytes流)
decode() 解碼 :將Bytes流轉化為字串
位元組流的格式:位元組流語法格式(前面加b) : b"123"
strvar = b"123" strvar = b"abc" # 中文不能在字串前面加b,必須是ascii編碼才能加; # strvar = b"你好" error print(strvar , type(strvar)) # b'123' <class 'bytes'>
中文和位元組流的轉化
# encode 編碼 strvar = "我愛你".encode("utf-8") print(strvar) # decode 解碼 res = strvar.decode("utf-8") print(res) # 三個位元組表達一箇中文字元 s_bytes = b'\xe7\x88\xb1' res = s_bytes.decode("utf-8") print(res)
檔案中寫入位元組流
"""mode = wb 代表寫入的是位元組流 , 不要指定任何編碼集 """ # 1.開啟檔案 fp = open("lianxi2",mode="wb") strvar = "愛上一匹野馬,家裡沒有草原" # 2.寫入位元組流 fp.write(strvar.encode()) # 3.關閉檔案 fp.close()
從檔案中讀位元組流
"""mode = rb 代表讀取的是位元組流 , 不要指定任何編碼集 """ # 1.開啟檔案 fp = open("lianxi2",mode="rb") # 2.讀取位元組流 res = fp.read() # 3.關閉檔案 fp.close() print(res) print(res.decode())
小例子:模擬複製圖片的過程
1 # 開啟原檔案,讀取其中的位元組流 2 fp = open("集合.png",mode="rb") 3 res = fp.read() 4 fp.close() 5 print(res) 6 7 # 把這些位元組流寫入到另外檔案中 8 fp = open("集合2.gif",mode="wb") 9 fp.write(res) 10 fp.close()View Code
總結: 二進位制位元組流比如:圖片,音訊,視訊 ... 資料使用二進位制位元組流進行拷貝
3.檔案的擴充套件模式
read() 功能: 讀取字元的個數(裡面的引數代表字元個數)
seek() 功能: 調整指標的位置(裡面的引數代表位元組個數)
seek(0) 把游標移動到檔案開頭
seek(0,2) 把游標移動到檔案末尾
tell() 功能: 當前游標左側所有的位元組數(返回位元組數)
1..r+ 先讀後寫
fp = open("lianxi.txt",mode="r+",encoding="utf-8") # 先讀 res = fp.read() # 後寫 fp.write("456") # 在讀 fp.seek(0) #因為檔案指標在檔案末尾,指向開頭 res = fp.read() print(res) fp.close()
2.r+ 先寫後讀
r+模式開啟後 檔案指標預設指向檔案的開頭,馬上寫入內容,會覆蓋原有的內容
fp = open("lianxi.txt",mode="r+",encoding="utf-8") # 先寫 fp.seek(0,2) # 開啟檔案後預設指向檔案開頭 fp.write("789") # 後讀 fp.seek(0) res = fp.read() print(res) fp.close()
3.w+ 可寫可讀
w+模式開啟檔案後,首先預設清空檔案,所以先讀後寫沒有意義;
fp = open("lianxi2.txt",mode="w+",encoding="utf-8") # 先寫 fp.write("123") # 後讀 fp.seek(0) print(fp.read()) fp.close()
4.a+ 可寫可讀
a+模式開啟後 檔案指標預設指向檔案的末尾,所以可以直接寫入內容
fp = open("lianxi3.txt",mode="a+",encoding="utf-8") fp.write('abc') fp.seek(0) print(fp.read()) fp.close()
5.比對a+和r+兩個模式之間的區別
r+模式下 寫入內容時,會隨著游標位置的改變而替換原有的字元
a+模式下 寫入內容時,會強制把游標移動到檔案的末尾
6.seek ,read , tell 三個方式的使用
read(單位) 單位根據檔案開啟的模式而產生變化,如果帶有b模式,讀取的是位元組的個數,否則讀取的是字元的個數
在移動seek時,小心游標移動到中文字元裡,在讀取內容時,產生無效的開始位元組
fp = open("lianxi.txt",mode="r+",encoding="utf-8") fp.seek(6) res = fp.tell() #6 print(res) res = fp.read(3) print(res) res = fp.tell() print(res) fp.close()
7. with語法 (上下文管理器)可以省略掉close操作
with open("ceshimv.mp4",mode="rb") as fp1 , open("ceshimv2.mp4",mode="wb") as fp2: res = fp1.read() fp2.write(res)
3.檔案相關的方法
1.重新整理緩衝區 flush
重新整理緩衝區有一下幾種情況
(1). 當檔案關閉的時候自動重新整理緩衝區
(2).當整個程式執行結束的時候自動重新整理緩衝區
(3)當緩衝區寫滿了 會自動重新整理緩衝區
(4)手動重新整理緩衝區
2.檔案相關函式
1.readable() 功能: 判斷檔案物件是否可讀
2.writable() 功能: 判斷檔案物件是否可寫
3.readline() 功能 :讀取檔案一行內容
(1) .先讀取一行,如果內容不是空,列印這行資料,在讀取下一行進行判斷
with open("lianxi.txt",mode="r",encoding="utf-8") as fp: res = fp.readline() while res: print(res) res = fp.readline()
(2).readline(2) 2個字元個數
如果讀取個數 > 當前行總個數 : 按照當前行讀取
如果讀取個數 < 當前行總個數 : 按照個數讀取
4.readlines 功能:將檔案中的內容按照換行讀取到列表當中
5.writelines() 功能:將內容是字串的可迭代性資料寫入檔案中 引數:內容為字串型別的可迭代資料
6.truncate() 功能: 把要擷取的字串提取出來,然後清空內容將提取的字串重新寫入檔案中 (位元組)
with open("lianxi4.txt",mode="r+",encoding="utf-8") as fp: fp.truncate(9)
二.函式
1.函式基本格式
定義函式 def 函式名(): code1 code2... 呼叫函式 函式名()
2.函式的命名
字母數字下劃線,首字元不能為數字;
嚴格區分大小寫,且不能使用關鍵字;
函式命名有意義,且不能使用中文哦;
1.駝峰命名法:
(1)大駝峰命名法:mycar => MyCar每個單詞首字元大寫 (面向物件中 => 類)
(2)小駝峰命名法: mycar => myCar除了第一個單詞首字元小寫外,剩下的每個單詞首字元大寫 (用在函式中 .. )
2.命名法: 單詞和單詞之間用_分開 mycar => my_car
3.函式的引數
函式的引數的種類: 1.形參 2.實參
1.形參: 形式上的引數,在函式的定義處
2.實參: 實際上的引數,在函式的呼叫處
形參種類: 1.普通形參(位置形參) 2.預設形參 3.普通收集形參 4.命名關鍵字形參 5 關鍵字收集形參
實參種類: 1.普通實參 2.關鍵字實參
1.普通形參
"""hang,lie是普通形參(位置形參)""" def func(hang,lie): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 # 呼叫函式 """10,10是普通實參""" func(10,10) func(3,8)
2.預設形參
hang=10,lie=10 是預設形參,如果給與了實參,那麼使用實參值,如果沒有給與實參,那麼使用預設值
def func(hang=10,lie=10): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 # 呼叫函式 # func() func(5) # func(4,6)
3.普通形參 + 預設形參
hang普通形參,lie=10預設形參
注意點:預設形參必須跟在普通形參的後面
def func(hang,lie=10): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 # func(5) func(5,6)
4.關鍵字實參
關鍵字實參的順序可以任意顛倒
注意點: 關鍵字實參必須寫在普通實參的後面
def func(hang,a,b,c,lie=10): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 func(3,4,b=5,lie=7,c=6)
區別關鍵字實參和預設形參:
1.在def定義處,使用的引數是預設形參
2.在函式的呼叫處,使用的引數是關鍵字實參
5.普通收集引數
功能: 專門用來收集那些多餘的沒人要的普通實參
語法: 在引數的前面加上一顆星
返回: 一個元組
def func(a,b,c,*args): print(a,b,c) #1 2 3 print(args) # (43,44) func(1,2,3,43,44)
計算任意個數值的累加和
1 def func(*args): 2 print(args) # (1, 2, 3, 4, 5, 6, 7) 3 total = 0 4 for i in args: 5 total += i 6 print(total) 7 8 func(1,2,3,4,5)View Code
6.關鍵字收集引數
功能: 專門用來收集那些多餘的沒人要的關鍵字實參
語法: 在引數的前面上加上二顆星星
返回: 一個字典
def func(a,b,c,**kwargs): print(a,b,c) # 1 4 3 print(kwargs) #{'f': 5, 'z': 10, 'x': 30} func(a=1,c=3,f=5,b=4,z=10,x=30)
做任意個數值的字串拼接
1 """ 2 顏值擔當: 李雅琪 3 靚麗女生: 王永捐 4 普通顏值: 於盛林, 荷葉 , 吳洪昌 5 """ 6 7 def func(**kwargs): 8 strvar1 = '' 9 strvar2 = '' 10 dic = {"beautiful_boy":"顏值擔當" , "beautiful_girl":"靚麗女生"} 11 print(kwargs) # {'beautiful_boy': '李雅琪', 'beautiful_girl': '王永捐', 'common1': '於盛林', 'common2': '荷葉', 'common3': '吳洪昌', 'first': '菲菲', 'last': '石磊'} 12 for k,v in kwargs.items(): 13 # print(k,v) 14 # 如果該鍵在dic當中,說明是預定義角色,要獲取該角色是什麼 : 顏值擔當 靚麗女生 15 if k in dic: 16 # 顏值擔當 : 李雅琪 + '\n' 17 # 靚麗女生 : 王永捐 + '\n' 18 strvar1 += dic[k] + ":" + v + '\n' 19 else: 20 # 於盛林, 荷葉, 吳洪昌, 菲菲, 石磊, 21 strvar2 += v + "," 22 23 24 print(strvar1.strip()) 25 print( "普通顏值:" , strvar2.strip(",") ) 26 27 func(beautiful_boy = "李雅琪",beautiful_girl="王永捐",common1="於盛林",common2="荷葉",common3="吳洪昌",first="菲菲",last="石磊")View Code
7命名關鍵字形參
如果是命名關鍵字形參 , 在呼叫函式時,必須使用關鍵字實參的方式呼叫
(1) def func(a,b,*,c,d) 在星號後面定義的是命名關鍵字形參
def func(a,b,*,c,d): print(a,b) print(c) print(d) func(1,2,c=3,d=4)
(2) def func(*args,c,**kwargs) 在普通收集和關鍵字收集形參之間的是命名關鍵字形參
print("<=========>") def func(*args,c,**kwargs): print(args) print(c) print(kwargs) func(1,2,3,4,45,a=1,b=2,c=3)
8.* 和 ** 的使用方法
(1) 在定義處: 負責收集打包資料
* : 負責收集打包成元組
**: 負責收集打包成字典
(2) 在呼叫處: 負責打散解包資料
* : 負責對list tuple str set 打散解包成單獨的資料
**: 負責對dic 打散解包成單獨的鍵=值的形式
# 函式的定義處 def func(a,b,*,c,d): print(a,b) print(c,d) lst = [1,2] # 打散之後,把列表裡面的元素一個個拿出來作為函式的引數進行呼叫 tup = (1,2) set1 = {"aaa","bbb"} str1 = "ab" dic = {"aaaa":1,"bbbb":2} # 獲取的是字典的鍵 # 函式的呼叫處 一顆星 *可迭代資料前面 func(*dic,c=3,d=4) # func(1,2,c=3,d=4) # 函式的呼叫處 二顆星 **只能在字典前面修飾; dic = {"c":3,"d":4} func(1,2,**dic) # 把字典打散,抽離其中的鍵值對,變成 => c=3,d=4 關鍵字實參,作為引數呼叫函式;
函式的引數定義順序:
普通形參(位置形參) => 預設形參 => 普通收集形參 -> 命名關鍵字形參 -> 關鍵字收集形參;
4.return
return : 會把函式內部的值返回到函式的呼叫處;
(1)return後面可以接 6大標準資料型別 ,還可以接函式,類,物件,如果沒有自定義返回值,預設返回的None
(2)執行完return之後,函式直接終止,後面的程式碼不執行;
5.全域性變數 和 區域性變數
區域性變數: 在函式內部定義的變數是區域性變數
全域性變數: 在函式外部或者在函式內部使用global定義的變數是全域性變數
作用域: 作用的範圍
區域性變數: 在函式的內部
全域性變數: 橫跨整個檔案
生命週期:變數存活的時間
內建變數 > 全域性變數 > 區域性變數
1.區域性變數
def func(): # 建立一個區域性變數 a = 1 # 獲取區域性變數 print(a) # 修改一個區域性變數 a = 10 print(a) func() # print(a) error
2.全域性變數
方法一 :在函式外部定義的是全域性變數
# 建立一個全域性變數 b = 100 # 獲取全域性變數 print(b) # 修改全域性變數 b = 299 print(b) def func(): # 全域性變數可以直接在函式內部呼叫 print(b) func()
方法二: 在函式內部定義全域性變數,依賴global
def func(): # 宣告一個全域性變數c global c # 建立一個全域性變數 c = 99 func() print(c)
# 在函式內部修改全域性變數 d = 200 def func(): global d d = 300 func() print(d) #300
global總結:
如果函式外部沒有該全域性變數,那麼可以通過global在函式內部直接建立一個全域性變數
如果函式外部有該全域性變數,那麼可以通過global在函式內部修改當前全域性變數
6.函式名的使用
python中的函式可以像變數一樣,動態建立,銷燬,當引數傳遞,作為值返回,作為容器中的元素.叫第一類物件.其他語言功能有限
1 # 1.動態建立 2 def func(): 3 print("我是func1 ... ") 4 print(type(func)) 5 a = 1 6 print(type(a)) 7 a = func 8 a() 9 10 # 2.動態銷燬 11 del a 12 # a() error 13 # func() 14 15 # 3.當引數傳遞 16 def func1(f): 17 f() 18 19 def func2(): 20 print("我是func2 ... ") 21 22 func1(func2) 23 24 # 4.作為值返回 25 def func1(f): 26 return f 27 28 def func3(): 29 print("我是func3 ...") 30 res = func1(func3) 31 res() 32 33 # 5.可以把函式作為容器中的元素 34 def func1(): 35 print("我是func1 .. ") 36 def func2(): 37 print("我是func2 .. ") 38 def func3(): 39 print("我是func3 .. ") 40 lst = [func1,func2,func3] 41 for i in lst: 42 i() 43 44 45 # ### __doc__ 用來檢視幫助文件 46 def wash(something): 47 48 """ 49 功能: 洗衣服的過程 50 引數: something => 衣服 51 返回值: 洗完的狀態 52 """ 53 54 print( "先脫{}".format(something) ) 55 print("放在桶裡") 56 print("到點洗衣液") 57 print("泡水,搓一搓") 58 print("穿上~") 59 return "洗完了" 60 61 wash("衣服") 62 63 # __doc__ 函式.__doc__ 獲取函式內部自定義文件; 64 res = wash.__doc__ 65 print(res)View Code
7.函式的巢狀
互相巢狀的兩個函式:
外層函式即外函式
內層函式即內函式
def outer(): inner() def inner(): print("我是內函式 ... ")
(1)內部函式不可以直接在函式外部呼叫
(2)呼叫外部函式後,內部函式不可以在函式外部呼叫
(3)內部函式可以在函式內部呼叫嗎
(4)內部函式在函式內部呼叫時,必須先定義函式,在呼叫函式,沒有預載入機制
三層函式巢狀,最外層是outer,中間層是inner ,最裡層 smaller , 呼叫smaller函式
def outer(): def inner(): def smaller(): print("我是smaller函式 ... {}".format(id)) smaller() inner() outer() print(outer)
LEGB 就近找變數原則:
找尋變數的呼叫順序採用LEGB原則(即就近原則)
B —— Builtin(Python);Python內建模組的名稱空間 (內建作用域)
G —— Global(module); 函式外部所在的名稱空間 (全域性作用域)
E —— Enclosing function locals;外部巢狀函式的作用域(巢狀作用域)
L —— Local(function);當前函式內的作用域 (區域性作用域)
依據就近原則,從下往上 從裡向外 依次尋找
8.nonlocal (修改區域性變數)
nonlocal 專門用來修改區域性變數,符合LEGB原則,就近找變數,
(1).找當前作用域上一層空間的變數值進行修改
def outer(): a = 1 def inner(): nonlocal a a = 10 print(a) #10 inner() print(a) #10 outer()
(2).如果上一層不存在,繼續向上一層空間進行尋找
def outer(): a = 199 def inner(): a = 201 def smaller(): nonlocal a a = 200 print(a) #200 smaller() print(a) #200 inner() print(a) #199 outer()
(3).直到最後找不到,直接報錯
a = 199 # 是全域性變數, 而nonlocal用來修改區域性變數; def outer(): def inner(): def smaller(): nonlocal a a = 200 print(a) smaller() print(a) inner() print(a) outer()
不通過 nonlocal 可以修改區域性變數
def outer(): lst = [10,20,30] def inner(): lst[0] = 100 inner() print(lst) #[100, 20, 30] outer()
9、閉包函式
互相巢狀的兩個函式,內函式使用了外函式的區域性變數,
外函式把內函式返回出來的過程,叫閉包,內函式叫做閉包函式
原則:
(1) 內函式使用了外函式的區域性變數
(2) 外函式將內函式返回return
1.閉包函式基本語法
def liyaqi_family(): father = "李嘉誠" def hobby(): print("我對錢沒有興趣,我只對捐錢感興趣,這是我爸爸{}說的".format(father)) return hobby res = liyaqi_family() res()
2.閉包的複雜語法
1 def liangruiqing_family(): 2 jiejie = "馬蓉" 3 meimei = "馬諾" 4 money = 1000 5 6 def jiejie_hobby(): 7 nonlocal money 8 money -= 600 9 print("喜歡出軌,喜歡花錢,喜歡買包包,手錶,GUCCI,chanel...家裡的錢敗光了,還剩下{}".format(money)) 10 11 def meimei_hobby(): 12 nonlocal money 13 money -= 399 14 print("我就喜歡在寶馬裡面哭,不喜歡在自行車上面撒歡~...家裡的錢敗光了,還剩下{}".format(money)) 15 16 def big_master(): 17 return [jiejie_hobby,meimei_hobby] 18 19 # def func(): 20 # print(jiejie) 21 # return func 22 23 return big_master 24 25 26 func = liangruiqing_family() 27 # 獲取姐姐函式 28 jiejie = lst[0] 29 jiejie() #家裡的錢敗光了,還剩下400 30 # 獲取妹妹函式 31 meimei = lst[1] 32 meimei() 家裡的錢敗光了,還剩下1View Code
3.閉包的特點
互相巢狀的兩個函式形成了閉包;內函式使用了外函式的區域性變數,
該變數與內函式發生繫結,延長該變數的生命週期,直到該指令碼執行結束.
def outer(val): def inner(num): return val + num return inner func = outer(10) res = func(5) print(res) #15
4.閉包的意義
在做計數加1的過程當中,發現全域性變數的值範圍太大,導致可以被任意篡改,資料不安全
clicknum = 0 def func(): global clicknum clicknum += 1 print(clicknum) func() func() func() clicknum = 100 func() #101
出現的問題:單純的區域性變數不能累加1,
def clicknum(): x = 0 x += 1 print(x) clicknum() clicknum() clicknum()
閉包的意義:
閉包可以優先使用外函式中的變數,並對閉包中的值起到了封裝保護的作用.外部無法訪問
def clicknum(): x = 0 def func(): nonlocal x x += 1 print(x) return func func = clicknum() # func = 閉包函式func func() func() x = 100 func() #3
10.匿名函式
用一句話來表達只有返回值的函式叫做匿名函式
語法: lambda 引數 : 返回值
(1)無參的匿名函式
def func(): return "我是func1111" res = func() print(res) # lambda 改造 func = lambda : "我是func1111" print(func())
(2) 有參的匿名函式
def func(num): return type(num) res = func([1,2,3]) print(res) # lambda 改造 func = lambda num : type(num) print(func({"a":"1",'b':2}))
(3) 帶有判斷條件的匿名函式
三元(目)運算子 (只能在雙向分支上可以使用,單項多項都不行)
語法: 真值 if 條件表示式 else 假值 => 如果條件表示式是真的,返回真值,否則返回假值
def func(num): if num % 2 == 0: return "偶數" else: return "奇數" res = func(11) print(res) # lambda 改造 print("<=================>") func = lambda num : "奇數" if num % 2 == 1 else "偶數" print(func(102))
三.locals() 和 globals()
1.locals() 獲取當前作用域的變數
在函式外,獲取的是列印之前所有全域性變數
在函式內,獲取的是呼叫之前所有區域性變數
# 1.在函式外 a = 1 b = 2 dic = locals() c = 3 print(dic) #a b c 都要列印
# 2.在函式內 def func(): a = 1 b = 2 dic = locals() c = 3 print(dic) d = 4 f = 5 func() # #列印 a b g = 6
2 . globals() 獲取全域性變數
在函式外,獲取的是列印之前所有全域性變數
在函式內,獲取的是呼叫之前所有全域性變數
# 1.在函式外 a = 1 b = 2 dic = globals() c = 3 print(dic) ## a b c 都要列印
# 2.在函式內 def func(): a = 1 b = 2 dic = globals() c = 3 print(dic) d = 4 f = 5 func() ## 只打印 f g = 6
3 .利用globals批量建立全域性變數
globals實現,通過字串建立一個全域性變數
globals返回的是系統內建的一個字典
通過往內建字典中新增鍵值對,實現全域性變數的建立
dic = globals() # 通過往內建字典中新增鍵值對,實現全域性變數的建立 dic["wangwen"] = "王文" print(dic) print(wangwen) #"王文"
四、迭代器
迭代器:能被next()函式呼叫並不斷返回下一個值的物件稱為迭代器(Iterator 迭代器是物件)
概念:迭代器指的是迭代取值的工具,迭代是一個重複的過程,每次重複都是基於上一次的
結果而繼續的,單純的重複並不是迭代
特徵:並不依賴索引,而通過next指標(記憶體地址定址)迭代所有資料,一次只取一個值,
而不是一股腦的把所有資料放進記憶體.大大節省空間
1、 可迭代性物件
如果一個物件中含有__iter__這個成員,說明該資料是可迭代性物件;
ps:檢視該物件中的成員,dir
setvar = {"白金鴿","楊特","郝建康"} # 檢視該物件中的成員,dir lst = dir(setvar) if '__iter__' in lst: print("該資料是可迭代性資料") print(lst)
2、 迭代器
如果是迭代器,一定是可迭代物件
如果是可迭代物件,不一定是迭代器;
1.如何變成一個迭代器
setvar = {"白金鴿","楊特","郝建康"} # 1.如何變成一個迭代器 it = iter(setvar) # 方法一 it = setvar.__iter__() # 方法二 lst = dir(it) print(lst)
2.如何判斷一個迭代器 __iter__ + __next__
if "__iter__" in lst and "__next__" in lst: print("該資料是迭代器")
3.如何呼叫一個迭代器
1 # 方法一 2 res = next(it) 3 print(res) 4 res = next(it) 5 print(res) 6 res = next(it) 7 print(res) 8 # res = next(it) error 9 # print(res) 10 11 # 4.重置迭代器 12 it = iter(setvar) 13 # res = next(it) 14 res = it.__next__() 15 print(res) 16 17 # 方法二 18 print("<=========>") 19 for i in it: 20 print(i) 21 # next(it) error 單項不可逆的過程 22 23 # 方法三 24 print("<=========>") 25 setvar = {"白金鴿","楊特","郝建康","於盛林","楊業","王娟娟","草配線","孟凡偉"} 26 it = iter(setvar) # setvar.__iter__() 27 for i in range(8): 28 print(next(it))View Code
五、高階函式
高階函式 : 能夠把函式當成引數傳遞的就是高階函式
1、map(func,Iterable) : 處理資料
功能:
把Iterable中的資料一個一個的傳遞到func函式當中進行處理,處理之後的結果通過迭代器一個一個獲取
引數:
func:內建或者自定義函式
Iterable : 可迭代性資料(容器型別資料 range物件 迭代器)
返回值:
迭代器
# (1) ["1","2","3","4"] => [1,2,3,4] lst = ["1","2","3","4"] lst_new = [] for i in lst: # print(int(i)) lst_new.append(int(i)) print(lst_new) # 使用map改寫 it = map(int,lst) for i in it: print(i,type(i)) print(list(it))
# (2) [1,2,3,4] => [5,10,15,20] lst = [1,2,3,4] lst_new = [] for i in lst: res = i * 5 lst_new.append(res) print(lst_new) # 使用map改寫 """ 注意點 : 引數和返回值必不可少""" def func(n): print(1111111111) return n * 5 it = map(func,lst)
2、reduce(func,Iterable) 計算資料
功能:
先把Iterable中的前兩個資料拿出來,扔到func中做處理,得出一個結果,
在拿當前結果和Iterable的下一個值在繼續扔到func做計算,
依次類推...
直到最後返回結果.
引數:
func : 自定義函式
Iterable : 可迭代性物件(容器型別資料 , range物件 , 迭代器)
返回值:
計算最後的結果
#(1) [5,4,8,8] => 5488 from functools import reduce def func(x,y): return x*10 + y lst = [5,4,8,8] res = reduce(func,lst) print(res,type(res)) # lambda 改造 print(reduce( lambda x,y : x*10 + y , lst))
# (2) "5488" => 5488 不讓使用int函式 def func(x,y): return x*10 + y def func2(n): dic = {} for i in range(10): dic[str(i)] = i return dic[n] # 功能: "5488" => 5,4,8,8 it = map(func2,"5488") # 功能: [5,4,8,8] => 5488 res = reduce(func,it) print(res , type(res))
3、filter(func,Iterable)過濾資料
功能:
通過自定函式的返回值控制當前資料保留與否
return True 代表保留
return False 代表捨棄
引數:
func : 自定義的函式
Iterable : 可迭代性資料(容器型別資料,range物件,迭代器)
返回值:
迭代器
# lst = [1,12,435,234,122,2] => 過濾掉偶數,保留奇數 lst = [1,12,435,234,122,2] lst_new = [] for i in lst: if i % 2 == 1: lst_new.append(i) print(lst_new) # 使用filter進行改造 def func(n): if n % 2 == 1: return True else: return False it = filter(func,lst) lst = list(it) print(lst) # 使用lambda 進行改造 print(list(filter( lambda n : True if n % 2 == 1 else False , lst )))
4、sorted(Iterable , reverse=False , key = 函式)
功能:
排序資料
引數:
Iterable : 可迭代物件 (容器型別資料 range物件 迭代器)
reverse : 正序或者倒序 reverse = False (從小到大)
key : 內建或者自定義方法
返回值:
排序後的資料(列表)
# 1.從小到大 lst = [-9,18,13,16,99,87] res = sorted(lst) print(res) # 2.從大到小 res = sorted(lst,reverse=True) print(res)
sort 和 sorted的區別:
[sorted] 推薦
1.sorted 可以對所有的容器型別資料排序
2.返回一個新的列表
[sort]
1.sort 只能對列表這一個型別進行排序
2.針對於原有的列表進行排序
六 、推導式
概念: 通過一行迴圈判斷,遍歷出一系列資料的方法就是推導式
推導式種類三種:
[val for val in Iterable] 列表推導式
{val for val in Iterable} 集合推導式
{a:b for a,b in iterable} 字典推導式
1.列表推導式
1.單迴圈推導式基本語法
# 建立列表,內容為1~50 lst = [ i for i in range(1,51) ] print(lst)
2.帶有判斷條件的單迴圈推導式
注意點: 在迴圈後面只能跟單項分支
# 1 ~ 100 中的所有偶數保留到列表裡 lst = [] for i in range(1,101): if i % 2 == 0 : lst.append(i) print(lst) # 改寫推導式 lst = [ i for i in range(1,101) if i % 2 == 0 ] print(lst
3.多迴圈推導式基本語法
lst1 = ["於盛林","荷葉","王永娟"] lst2 = ["李琦","朱培峰","劉靈鎮"] lst = [] for i in lst1: for j in lst2: lst.append(i + "♠" + j) print(lst) # 改寫推導式 lst = [ i + "♠" + j for i in lst1 for j in lst2 ] print(lst)
4.帶有判斷條件的多迴圈推導式
lst = [] for i in lst1: for j in lst2: if lst1.index(i) == lst2.index(j): lst.append(i + "♠" + j) print(lst # 改寫推導式 lst = [ i + "♠" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ] print(lst)
2.集合推導式
""" 案例: 滿足年齡在18到21,存款大於等於5000 小於等於5500的人, 開卡格式為:尊貴VIP卡老x(姓氏),否則開卡格式為:摳腳大漢卡老x(姓氏) 把開卡的種類統計出來 """ data = [ {"name":"李琦","age":22,"money":20000}, {"name":"李雅琪","age":19,"money":12000}, {"name":"吳洪昌","age":18,"money":5300}, {"name":"王召","age":80,"money":4000}, {"name":"王生父","age":81,"money":5400} ] setvar = set() for i in data: if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500: strvar = "尊貴VIP卡老{}".format(i["name"][0]) else: strvar = "摳腳大漢卡老{}".format(i["name"][0]) # 把對應的開卡格式存入到集合當中 setvar.add(strvar) print(setvar) # 改寫成集合推導式 # 三運運算子 + for迴圈 => 集合推導式 setvar = { "尊貴VIP卡老{}".format(i["name"][0]) if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "摳腳大漢卡老{}".format(i["name"][0]) for i in data } print(setvar)View Code
3.字典推導式
(1)enumerate
enumerate(iterable,[start=0])
功能: 列舉 ; 將索引號和iterable中的值,一個一個拿出來配對組成元組,通過迭代器返回
引數:
iterable: 可迭代性資料 (常用:迭代器,容器型別資料,可迭代物件range)
start: 可以選擇開始的索引號(預設從0開始索引)
返回值: 迭代器
lst = ["歡慶","尤佳","劉文波","黃長劍"] it = enumerate(lst) # 預設從0開始索引 it = enumerate(lst,start=1) # start = 1表示從1開始列舉配對;
# 1.配合enumerate完成字典推導式操作 dic = { k:v for k,v in enumerate(lst) } print(dic) # 2.直接通過dict強轉 dic = dict(enumerate(lst)) print(dic)
(2)zip(iterable, ... ...)
功能: 將多個iterable中的值,一個一個拿出來配對組成元組,通過迭代器返回
iterable: 可迭代性資料 (常用:迭代器,容器型別資料,可迭代物件range)
返回: 迭代器
原則: zip的配對原則會按照相同的索引組合,如果沒有相同的索引自動捨棄;
# 1.配合zip完成字典推導式操作 lst_key = ["zy","sxy","jyh"] lst_val= ["張印","孫翔宇","家營和"] dic = { k:v for k,v in zip(lst_key,lst_val) } print(dic) # 2.直接通過dict強轉 dic = dict(zip(lst_key,lst_val)) print(dic)
七、生成器
生成器本質是迭代器,允許自定義邏輯的迭代器
迭代器和生成器區別:
迭代器本身是系統內建的.重寫不了.而生成器是使用者自定義的,可以重寫迭代邏輯
生成器可以用兩種方式建立:
(1)生成器表示式 (裡面是推導式,外面用圓括號)
(2)生成器函式 (用def定義,裡面含有yield)
1、生成器表示式
# 生成器表示式 gen = (i for i in range(100)) print(gen) # generator # 呼叫生成器 # 1.next res = next(gen) print(res) # 2.for + next (推薦) for i in range(3): print(next(gen)) # 3.for (慎用,防止資料量較大時,形成類似於死迴圈的效果) # for i in gen: # print(i) # 4.list (慎用,防止資料量較大時,記憶體溢位,出現藍屏) lst = list(gen) print(lst)
2、生成器函式
yield 類似於 return
共同點在於:執行到這句話都會把值返回出去
不同點在於:yield每次返回時,會記住上次離開時執行的位置 , 下次在呼叫生成器 , 會從上次執行的位置往下走
而return直接終止函式,每次重頭呼叫.
1.生成器函式語法
def mygen(): print("one") yield 1 print("two") yield 2 print("three") yield 3 # 初始化生成器函式 => 返回生成器物件 , 簡稱生成器 gen = mygen() res = next(gen)
2.生成器優化寫法
def mygen(): for i in range(1,101): yield "新制造的籃球球衣號碼是{}".format(i) # 初始化生成器函式 => 返回生成器物件 , 簡稱生成器 gen = mygen() # 先獲取前30個數據 for i in range(30): print(next(gen))
3.send語法的使用
send send傳送值的時候,是給上一個yield
next和send區別:
next 只能取值
send 不但能取值,還能傳送值
send注意點:
第一個 send 不能給 yield 傳值 預設只能寫None
最後一個yield 接受不到send的傳送值
1 def mygen(): 2 print("start ... ") 3 res = yield "111" 4 print(res) 5 6 res = yield "222" 7 print(res) 8 9 res = yield "333" 10 print(res) 11 12 res = yield "444" 13 print(res) 14 print("end ... ") 15 16 # 初始化生成器函式 => 返回生成器物件 , 簡稱生成器 17 gen = mygen() 18 # 第一次傳送資料時,無腦加None 19 res = gen.send(None) 20 print(res) 21 res = gen.send("我來了老妹2") 22 print(res) 23 res = gen.send("我來了老妹3") 24 print(res) 25 res = gen.send("我來了老妹4") 26 print(res) 27 # res = gen.send("我來了老妹5") error 28 # print(res)View Code
4. yield from 的基本使用
yield from : 將一個可迭代物件變成一個迭代器返回
def mygen(): # yield [1,2,3,4,5] yield from [1,2,3,4,5] gen = mygen() print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen))