python装饰器原理
装饰器:遵循开放封闭原则,给已存在的功能,添加新功能。
首先:例如 函数login的函数名只是一个内存地址,函数login()才是执行函数
def login(func):
print("已经通过验证")
return func
@login #装饰器,将主函数作为参数传入login函数。
def play(name):
print("欢迎 {%s} 进入游戏" % name)
#play = login(play) 等价于 @login #装饰器原理
play('li')
程序过程(不完整的装饰器原理):
1:python解释器将从上往下读入代码,先将login读入到内存,但没有执行。因为没有login()
2:读到@login,python会先运行装饰器的函数名的函数,并将主函数的地址值作为参数,
传入函数体内(主函数现在相当于变成一个局部变量),所以该函数会打印print("已经通过验证"),
然后return func返回主函数的函数名的地址值。play = login(play),主函数被覆盖。
缺点:不调用新play该函数仍然会打印print("已经通过验证")
完整的装饰器
将login函数不执行,返回主函数
def login(func):
def inner(arg):
print("已经通过验证")
func(arg)
return inner
@login # 相当于play = inner 即原play函数被覆盖了
def play(name):
print("欢迎 {%s} 进入游戏" % name)
play('li')
程序过程(装饰器的原理):
1:python解释器将从上往下读入代码,先将login读入到内存,但没有执行。因为没有login()
2:读到@login,python会先运行装饰器名的函数,并将主函数(装饰器装饰的函数)的地址值作为参数,
传入装饰函数体内(主函数现在相当于变成一个局部变量),所以login函数会return inner返回inner函数的函数名的地址值。
该步相当于play = inner inner函数没有执行只是传了inner函数的地址值
3:读到play(‘li’)时候,相当于inner(‘li’),因为inner(‘li’)相当于执行函数inner并将’li’字符串作为参数传入inner函数,
4:inner(‘li’)函数开始执行,打印print("已经通过验证"),并通过局部变量func的地址值,开始执行func(arg)即执行func(‘li’),
func的地址值就是play,所以就相当于运行了play(‘li’)。该函数实现了执行play(‘li’)前,先执行验证。
带参数的装饰器(高级理解)
def Login(name):
print("欢迎 %s 登录游戏!!!" % name)
def Logout(name):
print("再见 %s,生活愉快!!!" % name)
def zsc(Login,Logout):
def zs(func):
def inner(arg):
Login(arg)
func(arg)
Logout(arg)
return inner
return zs
@zsc(Login,Logout)
def play(name):
print("%s正在玩游戏" % name)
play('li')
程序运行:
1:python读入Login,Logout,zsc三个函数,然后读入@zsc(Login,Logout),这里注意:python对于函数()是代表开始运行函数,
而不是读入内存,所以这里开始会先运行函数zsc(Login,Logout),返回了函数zs的函数地址值(注意是没有运行的)。
2:所以装饰器变成@zs了,python会先运行装饰器名的函数,并将主函数(装饰器装饰的函数)的地址值作为参数,传入装饰函数体内(主函数现在相当于变成一个局部变量),即执行zs(play)函数,该函数返回了inner函数的地址值(注意这里也没有执行inner函数),所以play(‘li‘)即为inner(‘li’),
所以结果
欢迎 li 登录游戏!!! (代表添加主函数运行前添加的功能)
li正在玩游戏 (代表主函数运行)
再见 li,生活愉快!!! (代表添加主函数运行后添加的功能)

浙公网安备 33010602011771号