一、装饰器的基本介绍
定义:装饰器本质是函数,(装饰其它函数)就是为其它函数添加附加功能
原则:
- a,不能修改被装饰的函数的源代码
- b,不能修改被装饰的函数的调用方式
实现:
- 函数即“变量”,(函数可以像变量一样用来赋值,如func1 = func2)
- 高阶函数:1,把一个函数名当作实参传给另一个函数;2,返回值中包含函数名
- 嵌套函数:def func1():def func2():pass
高阶函数+嵌套函数 =>装饰器
知识点:
作用域的取值是从内到外一层层的找
函数的调用,内存,返回值及赋值
1 def home_page(): 2 print(("home page").title().center(30,'@')) 3 return 'from home' 4 print(home_page()) #函数名加括号,表示执行函数,这里表示先调用函数,再打印函数的返回值 5 print('第一个') 6 print(home_page) #函数名指向的是一个内存地址,存的内容就是函数的内容,但是没有调用,打印的是它的内存地址 7 print('第二个') 8 a = home_page() #函数先调用,然后将返回值赋给a,a = 'from home',但是不打印a的值。如果函数没有return,那么a = None 9 print('第三个') 10 print(a) #打印a,a = 'from home' 11 print('第四个') 12 a = home_page #将函数home_page当作一个变量赋给a,那么a就是一个函数,和home_page一样(没有输出) 13 print('第五个') 14 a() #执行函数a,返回值不打印,和home_page()一样 15 print('第六个') 16 print(a()) #相当于print(home_page()) ,先调用,再打印返回值 17 print('第七个')
输出为:
1 @@@@@@@@@@Home Page@@@@@@@@@@@ 2 from home 3 第一个 4 <function home_page at 0x000000000081E1E0> 5 第二个 6 @@@@@@@@@@Home Page@@@@@@@@@@@ 7 第三个 8 from home 9 第四个 10 第五个 11 @@@@@@@@@@Home Page@@@@@@@@@@@ 12 第六个 13 @@@@@@@@@@Home Page@@@@@@@@@@@ 14 from home 15 第七个
装饰器最少两层:满足嵌套函数的要求。
最里面一层就是要装饰的函数实现的功能(调用最里层函数就相当于调用要装饰的函数)
外一层就是以要装饰的函数为参数,并返回最里面一层的函数
如果装饰器也需要加参数的话,那么外面再加一层函数,参数就是装饰器的参数,返回里面一层的函数名
实例:
1,被装饰的函数没有参数
1 def login(func): #func代表要装饰的函数名称 2 def inner(): #为vip_page和home_page连个函数添加验证登录的功能 3 user,password = 'cq','123' 4 while True: 5 user_name = input('>>>') 6 pass_word = input('>>>') 7 if user_name == user and pass_word == password: 8 func() #这里的func()相当于vip_page()。。 9 break 10 return inner #最外层函数返回里面一层的函数名称,不能加(),否则返回的是调用结果 11 12 def index_page(): 13 print("head page".title().center(30,'*')) 14 @login #vip_page = inner(vip_page) 15 def vip_page(): 16 print("vip page".title().center(30,'-')) 17 @login 18 def home_page(): 19 print(("home page").title().center(30,'@')) 20 return 'from home' 21 def nomal_page(): 22 print("nomal page".title()) 23 24 index_page() 25 vip_page() #并没有改变原来的调用方式,就增加了验证登录的功能
26 home_page()
27 nomal_page()
输出:
**********Head Page*********** >>>cq >>>123 -----------Vip Page----------- >>>cq >>>123 @@@@@@@@@@Home Page@@@@@@@@@@@ Nomal Page
2,被装饰的函数有参数
如果函数home_page有个参数,home_page(name)怎么办,另外如果函数vip_page有个返回值怎么办
1 def login(func): 2 def inner(*args,**kwargs): ##增加两个非固定参数,相当于inner(*args,**kwargs) = home_page(*args,**kwargs) 3 user,password = 'cq','123' 4 while True: 5 user_name = input('>>>') 6 pass_word = input('>>>') 7 if user_name == user and pass_word == password: 8 res = func(*args,**kwargs) #调用兵执行func,将返回值赋给res 9 return res #返回res,相当于返回vip_page()执行后的值 10 break 11 return inner 12 13 def index_page(): 14 print("head page".title().center(30,'*')) 15 @login 16 def vip_page(): 17 print("vip page".title().center(30,'-')) 18 return 'from home' 19 @login 20 def home_page(user): 21 print(("home page %s"%user).title().center(30,'@')) 22 def nomal_page(): 23 print("nomal page".title()) 24 25 index_page() 26 print(vip_page()) ##调用并打印vip_page的返回值 27 home_page('laocui') 28 nomal_page()
输出:
**********Head Page***********
>>>cq
>>>123
-----------Vip Page-----------
from home
>>>cq
>>>123
@@@@@@@Home Page Laocui@@@@@@@ #参数打印了出来
Nomal Page
3,装饰器有参数
再增加一个功能,如果登录类型是local,那么还是按照上面判断用户名那样执行,如果,登录类型是ldap,那么直接退出
1 def login(log_type): #此参数代表装饰器的参数 2 def outer(func): #参数是要装饰的函数 3 def inner(*args,**kwargs): 4 user,password = 'cq','123' 5 if log_type == 'local': 6 while True: 7 user_name = input('>>>') 8 pass_word = input('>>>') 9 if user_name == user and pass_word == password: 10 res = func(*args,**kwargs) 11 return res 12 break 13 elif log_type == 'ldap': #如果登录类型是ladap,那么不要登录 14 print('暂时不会ldap。。。。') 15 return inner #每个都要返回里面一层的函数名称 16 return outer #每个都要返回里面一层的函数名称 17 18 def index_page(): 19 print("head page".title().center(30,'*')) 20 @login('ldap') 21 def vip_page(): 22 print("vip page".title().center(30,'-')) 23 @login('local') 24 def home_page(user): 25 print(("home page %s"%user).title().center(30,'@')) 26 return 'from home' 27 def nomal_page(): 28 print("nomal page".title())
输出:
**********Head Page*********** 暂时不会ldap。。。。 >>>cq >>>123 @@@@@@@@@Home Page Cq@@@@@@@@@ from home Nomal Page