閉包:
關於閉包,即函數定義和函數表達式位於另一個函數的函數體內(嵌套函數)。而且,這些內部函數可以訪問它們所在的外部函數中聲明的所有局部變量、參數。當其中一個這樣的內部函數在包含它們的外部函數之外被調用時,就會形成閉包。也就是說,內部函數會在外部函數返回後被執行。而當這個內部函數執行時,它仍然必需訪問其外部函數的局部變量、參數以及其他內部函數。這些局部變量、參數和函數聲明(最初時)的值是外部函數返回時的值,但也會受到內部函數的影響。
def outer(): name = 'alex' def inner(): print("在inner裏打印外層函數的變量",name) return inner f = outer() f()
閉包的意義:
返回的函數對象,不僅僅是一個函數對象,在該函數外還包裹了一層作用域,這使得,該函數無論在何處調用,優先使用自己外層包裹的作用域
裝飾器:
一個裝飾器(decorator)只是一個帶有一個函數作爲參數並返回一個函數的閉包
裝飾器的作用就是爲已經存在的函數或對象添加額外的功能
例一:
不加參數的裝飾器:
# _*_coding:utf-8_*_ user_status = False #用戶登錄了就把這個改成True def login(func): #把要執行的模塊從這裏傳進來 def inner():#再定義一層函數 _username = "alex" #假裝這是DB裏存的用戶信息 _password = "abc!23" #假裝這是DB裏存的用戶信息 global user_status if user_status == False: username = input("user:") password = input("pasword:") if username == _username and password == _password: print("welcome login....") user_status = True else: print("wrong username or password!") if user_status == True: func() # 看這裏看這裏,只要驗證通過了,就調用相應功能 return inner # 用戶調用login時,只會返回inner的內存地址,下次再調用時加上()纔會執行inner函數 @login #america = login(america) def america(): #login() #執行前加上驗證 print("----歐美專區----") def japan(): print("----日韓專區----") @login def henan(): #login() #執行前加上驗證 print("----河南專區----") henan() 例二:
帶參數的裝飾器:
# _*_coding:utf-8_*_ user_status = True #用戶登錄了就把這個改成True def login(auth_type): #把要執行的模塊從這裏傳進來 def auth(func): def inner(*args, **kwargs):#再定義一層函數 if auth_type == "qq": _username = "alex" #假裝這是DB裏存的用戶信息 _password = "abc!23" #假裝這是DB裏存的用戶信息 global user_status if user_status == False: username = input("user:") password = input("pasword:") if username == _username and password == _password: print("welcome login....") user_status = True else: print("wrong username or password!") if user_status == True: return func(*args,**kwargs) # 看這裏看這裏,只要驗證通過了,就調用相應功能 else: print("only support qq ") return inner #用戶調用login時,只會返回inner的內存地址,下次再調用時加上()纔會執行inner函數 return auth def home(): print("---首頁----") @login('qq') def america(style): #login() #執行前加上驗證 print("----歐美專區----") def japan(style): print("----日韓專區----") @login('qq') ## henan = login('qq')(henan('3p')) def henan(style): ''' :param style: 喜歡看什麼類型的,就傳進來 :return: ''' #login() #執行前加上驗證 print("----河南專區----") home() # #那用戶調用時依然寫 america('3p') henan('3p')
例三:
計算函數運行時間的裝飾器:
# _*_coding:utf-8_*_ import string, random,time,datetime def count_time(type): def inner(): start = datetime.datetime.now() # time.sleep(2) # print(random.sample(string.ascii_letters + string.digits, 6)) obj = type() end = datetime.datetime.now() print(end - start) return obj return inner @count_time def rand(): print(random.sample(string.ascii_letters + string.digits, 6)) time.sleep(5) rand() 輸出: ['X', 'm', 'r', '7', 'l', 'D'] 0:00:05.000630
例四:
import time,random,string def count_time(type): def inner(*args, **kwargs): start = time.time() L = type(*args, **kwargs) end = time.time() print('程序運行時間%s秒' % (end - start)) return L return inner @count_time def string_create(): print(random.sample(string.digits + string.ascii_letters, 6)) time.sleep(3) string_create() 輸出: ['O', 'y', 'R', 'V', 'u', '3'] 程序運行時間3.000283718109131秒