高級函數
閉包
# 定義:如果在一個內部函數里,對在外部作用域(但不是在全局作用域)的變量進行引用,那么內部函數就被認為是閉包(closure) # 閉包 = 函數塊+定義函數時的環境,inner就是函數塊,x就是環境,當然這個環境可以有很多,不止一個簡單的x。 def outer(): x = 10 def inter(): # x = 10 print("inter:", id(inter))
# python解釋器在解釋代碼的時候,會檢測一下函數里面的變量是否引用外部函數變量名,如果有,就不會從內存中清除此變量 print(x) # 等於此時print(10)已經在內存里面,所以直接調用就可以用 return inter # inter就是一個閉包 inter = outer() # outer的返回值是inter,並且賦值給inter,相當於inter可以直接調用,返回的是inter的內存地址, inter()
1 def outer(x): 2 3 def inter(): # x = 10 4 print("inter:", id(inter)) 5 y = x 6 print(y) 7 print(x * 3) # 即使x是函數參數,因為內部函數引用了此變量名,依然不會被釋放 8 9 return inter # inter就是一個閉包 10 11 12 inter = outer(10) 13 inter()
裝飾器
有這樣一個函數
1 import time 2 3 4 def foo(): 5 time.sleep(3) 6 print("this foo.....")
需求,在不改動foo函數的前提下,計算出這個函數運行了長時間
方式一
1 def show_time(func): 2 start = time.time() 3 func() 4 end = time.time() 5 print(end - start) 6 return show_time 7 8 # 將foo函數作為變量,傳入show_time函數中, 9 show_time(foo)
方式二 使用裝飾器方式
1 無參數 2 import time 3 def show_time(func):#裝飾函數盡量放在上面 4 def inner(): 5 start = time.time() 6 func()# 因為閉包的原因,func參數並沒有被釋放,現在參數傳遞的是foo 7 end = time.time() 8 print(end - start) 9 return inner 10 11 @show_time #完全等於foo = show_time(foo) 裝飾哪個函數,就在那個函數之前添加 12 def foo(): 13 time.sleep(3) 14 print("this foo.....") 15 16
本質 foo = show_time(foo)
17 foo()
# 普通參數 or 其他參數 def show_time(func): def inner(x, y):# 此處 start = time.time() func(x, y)# 此處 不管是 x,*args,**kwargs 都同add參數 end = time.time() print(end - start) return inner @show_time def add(x, y): time.sleep(2) print("各種復雜乘...耗時...", x * y) add(3,6)
# 終極參數(裝飾器參數) # import time def looger(flag): def show_time(func): def inner(*x,**y): start = time.time() func(*x,*y) end = time.time() print(end - start) if flag == True: print("日志記錄") return inner return show_time @looger(True)#looger加()了,所以執行了looger函數,返回show_time 此時是@show_time,然后add=show_time(add) => add() == inner() def add(*x,**y): sums = 0 for i in x: sums += sums print(sums) time.sleep(0.5) add(3)
# 多個裝飾器 裝飾器執行順序從下而上,函數執行從上而下 def wrap_one(func): print("first one") def inner_a(): print("inner_a") func() return inner_a def wrap_two(func): print("first two") def inner_b(): print("inner_b") func() return inner_b @wrap_one @wrap_two def test(): print("test") test()
#有返回值的函數 def show_time(func): def inter(x, *args, **kwargs): begin_time = time.time() res = func(x, *args, **kwargs)# 執行完用變量接收,計算完時間在返回 end_time = time.time() print("時間:%s" % (end_time - begin_time)) return res # 處理帶有返回值的函數,別裝飾的有return,裝飾器也必須有return return inter @show_time def add(x, *args, **kwargs): time.sleep(1) return "我轉了一圈發現涼了" add(1, 2, 32134, 345, 345)
python內置函數
官方地址:https://docs.python.org/zh-cn/3/library/functions.html?highlight=built#ascii
關於序列化的內置函數
map函數
# 需求 將列表里面的每個值都平方一下,在生成一個新列表 data_list = [2, 5, 6, 7]
# 方式一 單純的循環 temp = [] for data in data_list: temp.append(data ** 2) print(temp) # [4, 25, 36, 49] # 方式二 map函數 # 第一個參數是函數,第二個參數是 iterable(可迭代) 對象, # map會循環第二個參數里面的每個值,經過第一個參數的函數處理,保存到迭代器對象中 result = map(lambda x: x ** 2, [1, 2, 3, 4]) print(list(result))#[1, 4, 9, 16]
filter函數
# filter函數 # 需求,假設下面的列表是某班的成績,列出大於60 的分數,並且生成新的字典 data_list = [ {"name":"張三","score":36}, {"name":"里斯","score":60}, {"name":"網速","score":59}, {"name":"小劉","score":80}, {"name":"王琦","score":90}, {"name":"啥酒","score":66}, ] # 方式一 單純的循環 temp = [] for data in data_list: if data["score"] >= 60: temp.append(data) print(temp) # [{'name': '里斯', 'score': 60}, {'name': '小劉', 'score': 80}, {'name': '王琦', 'score': 90}, {'name': '啥酒', 'score': 66}] # 方式二 filter函數 # result = filter(lambda x:x if x["score"]>=60 else False,data_list) # 結果同上,filter會用函數調用data_list里面的每個值,如果符合條件,將data_list里面的那個值保存到迭代器中 result = filter(lambda x:x["score"]>=60,data_list) print(list(result)) # [{'name': '里斯', 'score': 60}, {'name': '小劉', 'score': 80}, {'name': '王琦', 'score': 90}, {'name': '啥酒', 'score': 66}]