一、闭包函数
定义:定义在内部的函数引用外部函数的名字(变量)叫做闭包函数
要打印的是inner函数的x,因为这个函数里面没有定义x的值,所以找上一层的局部变量x = 111。执行代码,outter函数被调用,返回值为inner,用变量res接收,所以res = inner,下面再用res(),就是inner(),调用inner函数,执行里面代码,打印结果为111
def outter(): x = 111 def inner(): print(x) return inner res = outter() # res就是inner函数内存地址 res() #111
给函数体传值的两种方式:
1.函数调用时候直接传参
def index1(username): print(username) res = index1('aa') #aa
2.闭包传参
这个和刚开始定义的闭包函数一样只不过是把变量x,y放在outter函数里面当形参,在调用的时候传实参
def outter(x,y): # x = 1 # y = 40 def my_max(): if x > y: return x return y return my_max res1 = outter(1,40) # res就是my_max函数的内存地址 print(res1()) #40
二、装饰器
定义:给被装饰的对象添加新的功能的一个工具。 目的:更方便的使用新添加的新功能
装饰器(可调用对象)必须遵守的两个原则:
1.不可改变被装饰对象的代码
2.不可改变 被装饰对象的调用方式(假如调用方式是idnex(),使用装饰器之后也是这种调用方式)
简单版本:
在原始函数index函数上加一个时间计算功能,最后也是调用了index(),没有违反装饰器的两个原则。运行函数先到outter调用,里面传一个参数index(这个是最原始的index函数的内存地址),然后返回get_time,用变量index接收。index()其实就是调用get_time函数。执行里面代码,func()就是之前传的func参数,index()调用。
import time def index(): time.sleep(3) print('睡醒了') def outter(func): # func = 最原始的index函数的内存地址 def get_time(): start = time.time() func() # func = index函数的内存地址() 直接调用 end = time.time() print('index run time:%s'%(end-start)) return get_time index = outter(index) # outter(最原始的index函数内存地址) # index指向get_time函数的内存地址 index() #睡醒了
升级版本:(被装饰的函数需要参数,之前的用法需要在get_time里面的func()写参数,才能使用正确。统一参数写法:*args,**kwargs)
import time def index(): time.sleep(3) print('澳门最大线上赌场开业啦 性感tank在线发牌!') return 'index' # res1 = index() def login(name): time.sleep(1) print('%s is sb'%name) return 'login' # res = login('egon') def outter(func): # func = 最原始的login函数的内存地址 def get_time(*args, **kwargs): # args = ('egon',) kwargs = {} start = time.time() res = func(*args, **kwargs) # 最原始的login函数的内存地址() 直接调用 func('egon') end = time.time() print('func run time:%s'%(end-start)) return res return get_time login = outter(login) # outter(最原始的login函数的内存地址) res = login('egon') print(res) index = outter(index) res1 = index() print(res1)
这样设置之后可以接受任意参数的函数。
三、装饰器语法糖
语法糖在书写的时候应该与被装饰器紧紧挨着,两者之间不要有空。把装饰器赋值给紧挨这的的可调用对象,并且把紧挨着的函数名当做参数传递到装饰器中
四、多个装饰器一起使用
注意:装饰器装饰顺序:从下往上
装饰器执行效率:从上往下