• 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即可。

  • 相关阅读:
    centos7 下安装MongoDB
    centos7 学习笔记
    MongoDB相关资料收集
    centos 下安装.net core
    sql server 2008 r2 中的oracle发布使用笔记
    sql server 与oracle数据互导的一种思路--sql server链接服务器
    Visual Studio 2015正式版/产品密钥 Win10正式版官方原版ISO镜像下载大全&安装激活教程
    Modbus库开发笔记:Modbus ASCII Slave开发
    PID控制器开发笔记之十一:专家PID控制器的实现
    μCUnit,微控制器的单元测试框架
  • 原文地址:https://www.cnblogs.com/letgo-doo/p/8459966.html
Copyright © 2020-2023  润新知