python學習第四天,列表生產式,匿名函數,生成器,內置函數,叠代器,裝飾器,json和pickle的序列化和反序列化
阿新 • • 發佈:2017-12-12
數據 其他 imp 函數名 fun pro serializa and cal
列表生成式,生產器
#列表生成式,可以是代碼更復雜 a = [i for i in range(10)] #這裏的i,可以使用函數來裝飾 print(a) #生產器:就是數據在調用的時候才有 b = (x*2 for x in range(1000)) #print(b[3]),直接調用會報錯,因為數據還沒有生產呢 b.__next__() b.__next__() b.__next__() # print(b[1]),這也會報錯,因為生成器只保持當前數據 print(b.__next__())#只能使用這樣的方式取值 print((x*2 for x in range(10))) #將一個函數編程一個生成器#斐波那契數列 def feibo(max): n,a,b = 0 ,0,1 while n < max : # print(b) yield b #這樣就樣這個函數變成一個生成器了,生成器只有__next__()方法 a,b = b,a+b #這裏的意思是,將b賦值給a,將 a+b的結果賦值給b(這裏的a不是賦值後的a) #這句話的意思就是 t = tuple(b,a+b) n = n+1 return "done" # feibo(6) f = feibo(6) #這樣就將 函數給掛起了,運行其他的邏輯,然後在返回,當取到最後一個在next就會報錯,可以使用try except 來處理異常try: while True: f.__next__() except StopIteration as e:#將最後的返回值復制個e的這個異常對象中 print(e.value) #簡單的一個生產消費者模型 def consume(name): print("%s is begin"%name) while True: a = yield print("%s 開始消費 %s"%(name,a)) def provide(): #這裏有兩個消費者 c1 = consume("zhang") c2 = consume("yu") c1.__next__() c2.__next__() for i in range(10): c1.send(i)#這就是講i傳給上面yield這個地方 c2.send(i) provide() #什麽是叠代器,被next方法的叠代對象就是叠代器,其中list,set都是可叠代對象,但是不是叠代器 #可以直接做用於 for循環的對象,就是叠代對象 可以使用 from collections import Iterable #Iterator叠代器 from collections import Iterator isinstance("abc",Iterable)
匿名函數,內置函數
#1.匿名函數,就是沒有方法名的函數,使用 lamdba 關鍵字 a = lambda x:x+2 # lambda x:x+2 這就是一個匿名函數,x代表參數,x+2代表 函數體 print(a(3)) #2.內置函數 #1.abs()求絕對值 print(abs(-3.5)) all()#叠代器中所有的元素都為真,才是真 any()#叠代器中任何一個為真就是真 ascii()#將數字轉為ascii對象的值 bin()#轉為二進制 bool()#測試一個對象是正還是假 bytearray()#字節數組 callable()#是否可以調用 chr(),ord()#查看10進制對象的ascii/查看ascii對應的十進制 dir()#返回當前範圍內的變量 globals(),locals()#全局屬性,局部屬性 zip()#將兩個列表,1,1對應轉為一個新的列表 b= zip([1,2,3],["a","b","c"]) for i in b: print(i) from functools import reduce a = reduce(lambda x,y:x+y,range(10)) print(a,type(a)) #過濾器,按照fun,條件進行過濾,這裏可以直接使用匿名函數來簡化代碼 c = filter(lambda x:x<5, [i for i in range(10)]) for i in c: print(i) d = map(lambda x:x*2,[i for i in range(10)]) for i in d: print(i) #講map與reduce結合使用,求 1!+2!+3!+4! #階乘,這個是4的階乘 factorial = reduce(lambda f,c:f+c,map(lambda a:reduce(lambda x,y:x*y,range(1,a+1)),range(1,5))) print(factorial,type(factorial)) #排序 #將字典排序 info = {1:"a",5:"f",3:"c",2:"b",4:"d"} #1.按key進行排序 print(sorted(info.items())) #2.如果按value排序呢 print(sorted(info.items(),key = lambda x:x[1]))
裝飾器:
#1.高階函數,參數是函數,或者返回值是函數的 #嵌套函數,就是函數裏面在定義函數 #可以講函數,當成一個變量進行傳遞 #高階函數+嵌套函數==裝飾器 #裝飾器的作用就是,不改變原函數,不改變函數的調用方式 import time,pickle #1.高階函數 將函數作為參數傳遞 def deco1(func):#將函數當成一個變量傳遞過來,實際上是將函數的內存地址傳遞過來,函數名+()調用這個函數 start_time = time.time() func() end_time = time.time() print("%s這個函數運行是時間%d"%(func,end_time-start_time)) #deco1(func) #2.高階函數 返回值為函數 def deco2(func): start_time = time.time() #這句話的意思就是將func這個函數的內存地址返回去 return func end_time = time.time() print("%s這個函數運行是時間%d" % (func, end_time - start_time)) # func = deco2(func) # func() #3.嵌套函數,就是在函數裏面定義函數 def deco3(): def deco4(): print("deco4..run") #函數就相當於一個變量,定義一個函數,就相當於在內存空間聲明了一個內存地址 #所以這個地方一定要調用,要不只是聲明沒有調用的地方 deco4() # deco3() #如何對一個函數進行裝飾,並且不改變函數的調用方式 #例如對func()進行裝飾 #1.不改變函數的內部 def deco5(func): start_time = time.time() func() end_time = time.time() print("%s這個函數運行是時間%d" % (func, end_time - start_time)) #2.不改變函數的調用方式,(使用嵌套函數,再包一層,將包裝後的函數返回) def deco6(func): def waps(): start_time = time.time() func() end_time = time.time() print("%s這個函數運行是時間%d" % (func, end_time - start_time)) return waps @deco6 def func(): time.sleep(1) print("func運行") #這個是調用:這樣就實現的裝飾 # func = deco6(func)#這句話,python直接使用 @裝飾器名稱表示 # func() #如果函數帶有參數怎麽處理呢,就是在內部函數帶參數來接受被裝飾函數的參數 def deco7(func): def wrapper(name): start_time = time.time() func(name) end_time = time.time() print("%s這個函數%s運行是時間%d" % (func, name,end_time - start_time)) return wrapper @deco7 def func1(name): print("name",name) func1("aa") #如果func1有多個參數呢,所以使用可變參數來接受,最後修改為 def deco8(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) end_time = time.time() print("%s這個函數運行是時間%d" % (func, end_time - start_time)) return wrapper @deco8 def func2(name,age): time.sleep(1) # func2("zhang",22) #如果裝飾器自己也需要參數,改如何處理呢 #例如 #home 和 account 這兩個函數使用不同的登陸方式登陸的,如何使用一個裝飾器滿足所有需求 #這裏使用了同一張驗證方式,如果裝飾器上傳一個參數,代表這個方法不需要登陸該如何處理 def login(fun): def wrapper(*args,**kwargs): name = input("your namne") passwd = input("your password") if name == "zhang" and passwd == "123": fun(*args,**kwargs) else: print("登陸失敗") return wrapper def loginArg(type): def login(fun): def wrapper(*args,**kwargs): if type == "login" : name = input("your namne") passwd = input("your password") if name == "zhang" and passwd == "123": fun(*args,**kwargs) else: print("登陸失敗") elif type == "nologin" : fun(*args, **kwargs) return wrapper return login @loginArg(type="login") def home(name): print("%s in home"%name) #這個就不需要登陸 @loginArg(type="nologin") def account(name): print("%s in account"%name)
json序列化和pickle序列化
#序列化和反序列化json,pickle import json #json的load 與dump是保存和加載 json格式的文件 info = {"name":"zhang","age":22,"addr":"china"} info1 = [1,2,3,4,5,6,login] #這種info1中保存了一個函數的內存地址 # print(info1) with open("json","w") as f: # json.dump(info1,f) f.writelines(json.dumps(info)) #或者使用 # f.writelines(json.dumps(info1)) #這樣在使用json就會報錯,因為 function‘ is not JSON serializable with open("json","r") as f: # json.loads() # aa = json.load(f) #可以寫成 aa = json.loads(f.read()) print(type(aa))#可以看到,這樣的aa的類型是 dict,如果是一幫的 #json是所有語言都有的共性的 #這裏就使用pickle這個序列化,是python特有的個性的序列化 with open("pickle","wb") as f: pickle.dump(info1,f) #write() argument must be str, not bytes #這句話明顯表示,pickle.dump(info1,f)這需要一個(所以,這裏將文件的打開方式按照b形式打開) #或者寫成 # f.write(pickle.dumps(info1)) with open("pickle","rb") as f: # aa = pickle.load(f) aa = pickle.loads(f.read()) print(type(aa),aa) #這樣就可以取出來了,但是這裏有一個問題,因為列表中有一個函數,如果在另一個文件打開的話,這個函數會報錯,所以需要對這個函數特殊處理
python學習第四天,列表生產式,匿名函數,生成器,內置函數,叠代器,裝飾器,json和pickle的序列化和反序列化