装饰器有什么用?
当你需要给你多个函数加上同一个功能,例如登陆验证,计算程序运行时间。。。
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
开放封闭原则
1.对扩展是开放的
任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
装饰器的主要功能:
在不改变函数调用方式的基础上在函数的前、后添加功能。
做一个验证功能的装饰器:
status = False def login(func): # 这里func = change,这里的change是最初的change函数 def inner(): username = "xiaoming" password = 123 if status == False: _username = input("username:").strip() _password = input("password").strip() if _username == username and _password ==password: global status status = True print("认证成功") else: print("验证失败,用户名或密码错误") if status: return func() # 这里调用func就是调用最初定义的change函数 return inner # 返回inner @login # 这里@login 叫语法糖 相当于 change = login(change),执行后 login(change)= inner 即change = inner def change(): print("这是查询功能") ret = change() # 这里change()相当于调用inner(),ret接收的是inner函数的返回值即change函数 print(ret) # 这里打印的仍然是“这是查询功能”
带参数的装饰器,并且给登陆验证加上验证方式:
status = False def login(mode): # 这里login函数接收的是qq验证方式 print("使用%s验证方式" % mode ) def outer(func): # 这里的func依然是change函数 def inner(*args, **kwargs): username = "alex" password = "123" global user_status if status == False: _username = input("username:").strip() _password = input("password:").strip() if _username == username and _password == password: print("认证成功") user_status = True else: print("认证失败") if user_status: func(*args, **kwargs) return inner return outer @login("qq") # 这里@login(“qq”)相当于ss = login("qq") = outer , change = ss(change) = outer(change)= inner def change(sy, ac): print("这是查询功能", sy, ac) change(123, 456) # 这里依然是调用inner函数
多个装饰器装饰一个函数:
import time status = False def login(mode): # 3.这里login函数接收的是qq验证方式 print("使用%s验证方式" % mode) def outer(func): # 6.这里的func是t_inner函数 def inner(*args, **kwargs): # 9.这里开始执行inner username = "alex" password = "123" global user_status if status == False: _username = input("username:").strip() _password = input("password:").strip() if _username == username and _password == password: print("认证成功") user_status = True else: print("认证失败") if user_status: func(*args, **kwargs) # 10.到这里相当于执行t_inner函数 return inner # 7.返回inner给@login(qq)= inner = change return outer # 5.然后返回outer def delayed(func): # 2.第一次就会先执行这里 此时这里的func = 最初定义的change函数 def t_inner(*args, **kwargs): # 11.执行t_inner函数 time.sleep(3) return func(*args, **kwargs) # 12.执行最初定义的change函数 return t_inner # 3.t_inner作为delayed函数的返回值返回给@delayed = delayeg(change)= t_inner @login("qq") # 4.使用语法糖实现多个装饰器装饰一个函数是,先把语法糖走完在去调用函数。 走到这里时@login相当于ss = login("qq") = outer , change = ss(change) = outer(change)= inner,然后向下走 # 下面的语法糖走完后,此时@login会变成ss = login(“qq”) = ouder change = ss(delayed(change)= outer(t_inner)= inner @delayed # 1.这里@delayed相当于change = delayed(change)= t_inner 这里login函数接收的是qq验证方式,这里语法糖走完,开始第一次调用函数,此时前面的语法糖会发生变化 def change(sy, ac): # 13.调用change() print("这是查询功能", sy, ac) # 14.输出结果结束函数() return "功能成功调用" change(123, 456) # 8.这里调用change相当于调用inner()