python基础-装饰器

装饰器:装饰其他函数

原则:1.不能改变被装束函数内的源代码;2.不能改变其调用方式。用户看不出来函数被改变。

实现装饰器知识储备:

1.函数也是变量2.高阶函数3.函数嵌套。

高阶函数:把一个函数名当做实参传给另一个函数(不修改被装饰的函数源代码)或者返回值中包含函数名。

具体实现:

公司源代码:共享的一个黄色视频网站。

 1 def home():
 2     print("---首页----")
 3  
 4 def america():
 5     print("----欧美专区----")
 6  
 7 def japan():
 8     print("----日韩专区----")
 9  
10 def henan():
11     print("----河南专区----")
12 
13 home()
14 america()
15 henan()

 老总要求,改成想要看视频先进行用户认证,认证通过后判断时候为VIP,是才让看。

方法一:改函数源代码。不行

 1 user_status = False #用户登录了就把这个改成True
 2  
 3 def login():
 4     _username = "alex" #假装这是DB里存的用户信息
 5     _password = "abc!23" #假装这是DB里存的用户信息
 6     global user_status
 7  
 8     if user_status == False:
 9         username = input("user:")
10         password = input("pasword:")
11  
12         if username == _username and password == _password:
13             print("welcome login....")
14             user_status = True
15         else:
16             print("wrong username or password!")
17     else:
18         print("用户已登录,验证通过...")
19  
20 def home():
21     print("---首页----")
22  
23 def america():
24     login() #执行前加上验证
25     print("----欧美专区----")
26  
27 def japan():
28     print("----日韩专区----")
29  
30 def henan():
31     login() #执行前加上验证
32     print("----河南专区----")
33  
34  
35  
36 home()
37 america()
38 henan()
View Code

 方法二:不改源代码,改调用方式

 1 user_status = False #用户登录了就把这个改成True
 2  
 3 def login(func): #把要执行的模块从这里传进来
 4     _username = "alex" #假装这是DB里存的用户信息
 5     _password = "abc!23" #假装这是DB里存的用户信息
 6     global user_status
 7  
 8     if user_status == False:
 9         username = input("user:")
10         password = input("pasword:")
11  
12         if username == _username and password == _password:
13             print("welcome login....")
14             user_status = True
15         else:
16             print("wrong username or password!")
17  
18     if user_status == True:
19         func() # 看这里看这里,只要验证通过了,就调用相应功能
20  
21 def home():
22     print("---首页----")
23  
24 def america():
25     #login() #执行前加上验证
26     print("----欧美专区----")
27  
28 def japan():
29     print("----日韩专区----")
30  
31 def henan():
32     #login() #执行前加上验证
33     print("----河南专区----")
34  
35  
36  
37 home()
38 login(america) #需要验证就调用 login,把需要验证的功能 当做一个参数传给login
39 # home()
40 # america()
41 login(henan)
View Code

 用户每次调用时需要执行login(henan),类似的。其实稍一改就可以了呀。改成:

home()
america = login(america)
henan = login(henan)

 但问题在于,还不等用户调用 ,你的america = login(america)就会先自己把america执行了呀。。。。,你应该等我用户调用 的时候 再执行才对呀。。。

想实现一开始你写的america = login(america)不触发你函数的执行,只需要在这个login里面再定义一层函数,第一次调用america = login(america)只调用到外层login,这个login虽然会执行,但不会触发认证了,因为认证的所有代码被封装在login里层的新定义 的函数里了,login只返回 里层函数的函数名,这样下次再执行america()时, 就会调用里层函数啦。。。

代码三:

 1 def login(func): #把要执行的模块从这里传进来
 2  
 3     def inner():#再定义一层函数
 4         _username = "alex" #假装这是DB里存的用户信息
 5         _password = "abc!23" #假装这是DB里存的用户信息
 6         global user_status
 7  
 8         if user_status == False:
 9             username = input("user:")
10             password = input("pasword:")
11  
12             if username == _username and password == _password:
13                 print("welcome login....")
14                 user_status = True
15             else:
16                 print("wrong username or password!")
17  
18         if user_status == True:
19             func() # 看这里看这里,只要验证通过了,就调用相应功能
20  
21     return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数
22 
23 
24 @login#america = login(america)
25 def america():
26     #login() #执行前加上验证
27     print("----欧美专区----")
28  
29 def japan():
30     print("----日韩专区----")
31  
32 @login
33 def henan():
34     #login() #执行前加上验证
35     print("----河南专区----")

但是此版本不能传参数。稍作更改即可。

 1 user_status = False #用户登录了就把这个改成True
 2  
 3 def login(func): #把要执行的模块从这里传进来
 4  
 5     def inner(*args,**kwargs):#再定义一层函数
 6         _username = "alex" #假装这是DB里存的用户信息
 7         _password = "abc!23" #假装这是DB里存的用户信息
 8         global user_status
 9  
10         if user_status == False:
11             username = input("user:")
12             password = input("pasword:")
13  
14             if username == _username and password == _password:
15                 print("welcome login....")
16                 user_status = True
17             else:
18                 print("wrong username or password!")
19  
20         if user_status == True:
21             func(*args,**kwargs) # 看这里看这里,只要验证通过了,就调用相应功能
22  
23     return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数
24  
25  
26 def home():
27     print("---首页----")
28  
29 @login
30 def america():
31     #login() #执行前加上验证
32     print("----欧美专区----")
33  
34 def japan():
35     print("----日韩专区----")
36  
37 # @login
38 def henan(style):
39     '''
40     :param style: 喜欢看什么类型的,就传进来
41     :return:
42     '''
43     #login() #执行前加上验证
44     print("----河南专区----")
45  
46 home()
47 # america = login(america) #你在这里相当于把america这个函数替换了
48 henan = login(henan)
49  
50 # #那用户调用时依然写
51 america()
52  
53 henan("3p")

大致思路如下:通过账号认证后才能执行的函数,在不更改函数源代码和调用方式的情况下。定义一个认证函数,将原函数作为实参传给定义的认证函数。在认证函数内部在定义一个inner函数,次函数实现扩展功能。认证函数执行完毕后返回inner函数。上述函数为装饰器。需要装饰的函数,在函数体前加@login即可。

原文地址:https://www.cnblogs.com/letgo-doo/p/8459966.html