5.2函數小高級 5.2.1 函數當參數 1 函數也可以當返回值 練習 函數其實也是一種數據類型,可以當變數存儲 面試題 5.2.2 閉包 閉包的意義: 返回的函數對象,不僅僅是一個函數對象,在該函數外還包裹了一層作用域,這使得,該函數無論在何處調用,優先使用自己外層包裹的作用域 閉包 就是在內層函 ...
5.2函數小高級
5.2.1 函數當參數
- 1 函數也可以當返回值
def v(dar):
v = dar()
def n ():
print(444)
v(n)
# 實例2
def v():
print(666)
def n():
return v
m =n()
m()
# 實例3
def func():
print(555)
def info():
print(666)
return func()
v = info()
print(v)
練習
# 實例1 def v(): print(666) def n(): return v m =n() m() # 實例2 def v(): print(666) def n(): print('alex') v() n() # 實例3 name ='alex' def v(): print(name) def v1(): name = 'aicr' print(name) v() # alex v1() # aicr
函數其實也是一種數據類型,可以當變數存儲
# 實例1
def fucn():
print('alex')
list = [fucn,fucn,fucn()] # 加()直接執行了
list[0]()
list[1]()
# 實例2
def fucn():
print('alex')
dic = {'k1':fucn,'k2':fucn()}
dic['k1']()
- 面試題
'''用函數實現:
用戶輸入 f1 話費查詢
f2 餘額查詢
f3 人工服務
f4 寬頻業務
'''
# 方法1
usee = input('請輸入業務 :')
if usee =='f1':
print(話費查詢)
elif usee =='f2':
xxxxx
else:
xxxxxx
# 方法二 函數
def v1():
print('話費')
def v2():
print('餘額')
def v3():
print('人工')
def v4():
print('寬頻')
dic = {'f1':v1,'f2':v2,'f3':v3,'f4':v4}
usee = input('請輸入:')
dic[usee]()
5.2.2 閉包
- 閉包的意義:返回的函數對象,不僅僅是一個函數對象,在該函數外還包裹了一層作用域,這使得,該函數無論在何處調用,優先使用自己外層包裹的作用域
- 閉包 就是在內層函數調用外層函數的變數
# 實例1
def func():
a = 2
def info():
print(a) # 調用外層函數
info()
func()
# 實例 2
def get():
name = 'alex'
def info():
print(name)
return info # 返回info的記憶體id
v = get()
v() # 相當於調用info
# 實例 3
def get(arg):
def func():
return arg
return func()
v = get(666)
print(v)
1 閉包的作用:
- 1 保護變數,不受外部改變
作用 1 保護變數,不受外部改變
'''
a = 10
def func():
global a
a =2
def info():
global a
a = 3
先 func() 再 info() a =3
先 info() 再 func() a= 2
全局變數不穩定,受影響
'''
# 閉包
def func():
a = 10
def info():
print(a)
info()
# 這樣保護了變數不受其他影響
作用 2 使變數常駐記憶體
def func():
a = 10
def info():
print(a)
return info
v = func()
v()
2 查看是不是閉包
def func():
a = 10
def info():
print(a)
info()
print(info.__closure__) # 不是閉包返回 None
func()
3 閉包應用
'''
閉包 應用 簡易版爬蟲
'''
from urllib.request import urlopen
def func():
get = urlopen('https://www.dytt8.net/').read()
def info():
print(get)
return info
print('第一次,慢')
v = func()
v()
print('以後就在記憶體讀出')
v()
v() # 閉包常駐記憶體 , 直接記憶體讀出
5.2.3 lambda 函數表達式
三元運算
print('ture') if v > 6 else print('flase')
lambda ( 匿名函數)
v = lambda x: x*3
print(v(3))
v = lambda x,y:x*y
print(v(4,6))
# 三元運算和lambda
n = lambda x:x if x<4 else x+1
print(n(14))
# 也可以當作參數
lst = [lambda x: x*3 ,lambda x: x*3,lambda x: x*3 ]
n = lst[0](3)
print(n)
print(lst[1](3))
map + lambda
n = map(lambda x:x*5,[1,2,3,4]) for line in n : print(line)
5.4 高級函數
map (多對一)
# 實例1 n = map(lambda x : x+2,[1,2,3,4]) for i in n: print(i) # 實例2 lst =[map(lambda x:x+1,[1,2,3]),map(lambda x:x+2,[1,2,3]),map(lambda x:x+3,[1,2,3])] print(lst) '''[<map object at 0x000002B3D40B17F0>, <map object at 0x000002B3D40B1940>, <map object at 0x000002B3D40B1C50>]''' #實例3 lst =[map(lambda x:x+1,[1,2,3]),map(lambda x:x+2,[1,2,3]),map(lambda x:x+3,[1,2,3])] n = lst[0] for line in n : print(line) # 實例4 lst =[map(lambda x:x+1,[1,2,3]),map(lambda x:x+2,[1,2,3]),map(lambda x:x+3,[1,2,3])] for i in lst: for line in i: print(line)
filter 過濾掉不符合條件的數據
# 實例1 n = filter(lambda x :x>4,[1,22,33,4,5,]) for line in n: print(line) # 22,33,5 # 實例2 n = filter(lambda x :x if x<4 else print('flase') ,[1,22,3,4,5,]) for line in n: print(line)
5.5 推導式
列表
lst = [i for i in range(10)] lst1 = [1 for i in range(10)] lst2 = [ i for i in range(10) if i <6] # [迭代的變數 for i in 可迭代的對象 判斷 ] lst3 =[ i if i < 5 else 777 for i in range(10) ] print(lst5) # 加if 在for後 , 加 if ....else 在for前 lst4 = [lambda : i for i in range(10)] ''' v =[] for i in range(10): v.append(lambda :i) n = v[1]() print(n)''' lst5 = [ lambda x : x if x+i >10 for i in range(10)] def func(): pass lst6 = [func for i in range(10)] # 面試題 def func(): return [lambda x : x+i for i in range(10)] lst7 = [ i for i in func() ] print(lst7[1](7))
上面這個題。 不要死磕。 能明白多少就明白多少。 這個題對小白很不友好
元祖(集合)
# 元祖和集合都要循壞列印 set1 =(i for i in range(18 )) for i in set1: print(i) set1 ={lambda : i for i in range(18 )} for i in set1: print(i()) def func(): print(222) set3 = (func for i in range(10)) for i in set3: i()
字典
dic ={ 'k%d'%i:i for i in range(10)}
print(dic)
#同列表
5.6 遞歸
- 函數內部調用自己 (不建議,占記憶體)
- python 為了不爆記憶體 ,限制了遞歸次數1000次
# 實例1
def func(a):
print(a)
a = a +1
func(a)
func(1)
# 實例2
def func(a):
print(a)
if a < 5:
func( a + 1)
func(1) # 1,2,3,4,5
# 實例3
def func(a):
if a < 5:
func( a + 1)
print(a)
func(1) # 5,4,3,2,1
'''
函數在每進入下一層的時候,當前層的函數並未結束,它必須等它調用的下一層函數執行結束返回後才能繼續往下走。 所以最下麵的那句print(n)會等最裡層的函數執行時才會執行,然後不斷往外退層,所以會出現 5,4,3,2,1的效果
'''
# 實例 4
def func(a):
if a ==5:
return a
info = func(a + 1) + 10
return info
v = func(1)
print(v) # 34
5.7 裝飾器
1. 什麼是裝飾器
裝飾器就是在不改變原函數的情況下,調用函數前後增加代碼
def func(arg): def info(): print('aaaaaaaaaaaaaaaaaaa') arg() return info def v(): xxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx print(1111111111111) return 3333 data = func(v) data() def v1(): xxxxxxxxxxxxxxxxxxx print('alex') xxxxxxxxxxxxxxxxxxx lst = func(v1) lst() ''' 如果在 函數v 和函數v1 加上百行代碼, 你要一個一個加 函數如果不只有 v v1 很多 怎麼辦 -------------裝飾器-------------- ''' # 實例1 def func(arg): def info(): print('alrx sb') # 在調用函數前列印 alx sb arg() print('aaaaaaaaaaa') #在調用函數後列印 aaaaaaaaa return info def v(): print(1111111111111) data = func(v) # func的參數傳入v函數 此時data = info 函數 data() # 執行data = 執行 info() # 實例2 def func(arg): def info(): print('aaaaaaaaaaaaa') v = arg() return v return info def v(): print(1111111111111) return 3333 data = func(v) print(data())
2. 裝飾器基本格式
'''
上面的裝飾器很low 因為 如果裝飾上百個函數的話
要重覆 賦值操作
'''
def func(arg):
def info():
print('alex sb')
arg()
print('aaaaaaaaaa')
return info
@func
# @func 簡化 func函數的賦值
# @ 函數 第一步,調用func 把下麵的函數名當做func函數的參數 # arg = v
# 第二步 , func 的return info,賦值給下麵函數 v = info
# 但是 func中 arg還是指向 v函數id 而 v 重新的賦值
def v():
print(666)
v()
3.關於參數裝飾
# 實例1
'''
如果裝飾的函數需要傳參數
'''
def func(arg):
def info(a):
arg(a)
return info
@func
def data(n):
print(n)
data()
# 第一步 執行func(data)
# data = info函數
#執行data(參數)
########如果被裝飾的函數n個參數,需要改裝飾器
# 優化
def func(arg):
def info(*args,**kwargs):
arg(*args,**kwargs) # 加上*args **keargs 不用管被裝飾的函數需要幾個參數都能傳
return info
@func
def data(n1,n2,n3):
print(n1,n2,n3)
data(1,2,n3=3)
@func
def inner(a1,a2,a3,a4):
print(a1,a2,a3,a4)
inner('alex',1,2,3) # alex 1 2 3
裝飾器標準格式
def func(arg): def info(*args,**kwargs): data = arg() return data return info @func
4.關於返回值
# 實例1
def func(arg):
def info(*args,**kwargs):
data = arg(*args,**kwargs)
return data
return info
@func
def inner():
print('alex')
v = inner()
print(v) # none
# 實例2
def func(arg):
def info(*args,**kwargs):
data = arg(*args,**kwargs)
return data
return info
@func
def inner():
print('alex')
return 666
v = inner()
print(v) # 666
# 練習題
# 1 判斷文件是否存在
'''
imprt os
os.path.exists()
True or flase
'''
import os
def func(arg):
def info(*args,**kwargs):
# 檢查文件的路徑是否存在
lst= args[0]
if not os.path.exists(lst):
print('路徑不存在')
return None
data = arg(*args,**kwargs)
return data
return info
@func
def inner(path):
f1 = open(path,mode='r',encoding='utf-8')
v = f1.read()
print(v)
f1.close()
return True
v = inner("E:\代碼庫\電影下載地址.txt")
print(v)
5. 帶參數的裝飾器
# 實例1
def inner(a): # 在閉包外再嵌套一層,即帶參數的裝飾器
print(a)
def func(arg):
def info(*args,**kwargs):
data = arg(*args,**kwargs)
return data
return info
return func
@inner('alex')
# 執行 inner
# inner 返回的值func @func
# 執行ear = func(ear) = info
# 執行info函數
def ear(v):
print(v)
n = ear(111)
print(n)
# 實例2
def inner(a):
print(a)
def func(arg):
def info(*args,**kwargs):
data = arg(*args,**kwargs)
return data
return info
return func
@inner('alex')
def ear(v):
print(v)
return 666
n = ear(111)
print(n)
帶參數的裝飾器的執行過程其實是這樣的。 先inner(xxx) 然後inner函數返回值再和前面的@組合成裝飾器