一、闭包函数
闭包是指在一个函数中定义了另外一个函数,内函数运用了外函数作用域的名字,并且外函数的返回值是内函数的引用,这样就构成了一个闭包函数。
def callFunc(): n = 1 def show(): print('show: ', n) return show s = callFunc() s()
去掉了全局变量的使用,将show函数封装在callFunc函数的内部,使外部不可见,不能使用show函数,隐藏了实现细节。
程序在执行的时候,callFunc返回了内部定义的show函数,并且在show函数内部使用了外部函数的变量。
在show函数返回时,保存了当前的执行环境,也就是会在show函数中使用外部变量n。
n只是callFunc函数中的局部变量,当这个函数执行结束时,n自然而然就会被释放。
但是因为callFunc函数中返回了一个show函数,show函数还在外部执行,所以程序还会将show函数所需的执行环境保存下来
二、装饰器
装饰器是个什么东东呢?看字面意思好像是装饰什么东东的工具,其实你猜出大概意思了,装饰器本身就是一个函数,这个函数以闭包的形式定义使用 @装饰器函数名 形式来装饰,在不改源代码的情况下,让一个程序增加功能来进行装饰。
比如在一个项目中,有很多函数,由于项目越来越大,功能越来越多,导致程序越来越慢,其中一个功能函数功能,实现一百万次累加。
def my_count() s = 0 for i in range(1000001): s += i print('sum:',s)
现在要确定函数的运行时间,这个要怎么搞???如何能应用到所有函数上?
解决方法:
import time def count_time(func): def wrapper(): #wrapper 装饰 start = time.time() func() end = time.time() print('共计执行:%s 秒'%(end - start)) # 使用%d显示,取整后是0秒,因为不到一秒 return wrapper @count_time # 这实际就相当于解决方法3中的 my_count = count_tiem(my_count) def my_count(): s = 0 for i in range(10000001): s += i print('sum : ', s) my_count()
这样实现的好处是定义好了闭包函数后,只需要通过@xxx的装饰器语法,将@xxx加到要装饰的函数前
多层装饰器:
import time user_dic = {'is_login':None} def outter(func): def get_time(*args, **kwargs): start = time.time() res = func(*args, **kwargs) end = time.time() print('func run time:%s'%(end-start)) return res return get_time def login_auth2(data_source,x,t): def login_auth(func): def inner(*args, **kwargs): if user_dic['is_login']: res = func(*args, **kwargs) return res else: if data_source == 'file': username = input('please input your username:') password = input('please input your password:') if username == 'jason' and password == '123': user_dic['is_login'] = True res = func(*args, **kwargs) return res else: print('username or password error') elif data_source == 'MySQL': print('from MySQL') elif data_source == 'ldap': print('ldap') else: print('暂无该数据来源') return inner return login_auth @login_auth2('file',1,2) # 这一步相当于 # res = login_auth2('file',1,2) # 这里的res就是login_auth2()的返回值login_auth # @res @outter def index(): time.sleep(1) print('index') return 'index' index() # 装饰器在装饰的时候,顺序从下往上 # 装饰器在执行的时候,顺序从上往下 # 这里就实现了给index函数增加了两个功能:计时和认证 # 这里的认证函数是三层嵌套的,最外层函数的作用就是给里层函数传参
装饰器模板:
无参装饰器
from functools import wraps def outter(func): @wraps(func) def inner(*args, **kwargs): # * **在形参中使用 # 执行被装饰函数之前你可以做的操作 res = func(*args, **kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner @outter def index(username, *args, **kwargs): """index注释""" pass print(index)
有参装饰器
def wrappers(data): # data = 'file' def outter(func): def inner(*args,**kwargs): if data == 'file': # 执行被装饰函数之前你可以做的操作 res = func(*args,**kwargs) # * **在实参中使用 # 执行被装饰函数之后你可以做到操作 return res return inner return outter