zoukankan      html  css  js  c++  java
  • python装饰器

    装饰器就是一个函数,他是通过不修改某个函数的源代码和调用方式的前提下可以添加新功能的一种函数。在python 中装饰器一般采用高阶函数和嵌套函数达到装饰的作用,下面进行实例讲解:

    1、目前有一个网址有很多页面(比如:index,home,bbs)。因为时老文字,所有页面都是可以直接浏览的。实现效果如下:

    def home():#模拟网页homne
        print("wolcome to home")
    
    
    def bbs():#模拟网页bbs
        print("wolcome to bbs")
    
    
    index() #调用index
    home()  #调用home
    bbs()   #调用bbs
    

      运行结果如下:各个网站均可以直接浏览

    wolcome to index
    wolcome to home
    wolcome to bbs

    2、公司有了新规定要求主页indezx 保留原始状态直接浏览,home 和bbs 需要登录才能浏览,不允许修改目前的函数源代码和调用方式实现这个功能。这下则么办呢?

    我们可以为需要登录才能浏览的网页home 和bbs 函数进行装饰即可。

    user, passwd = 'dwdar', 'abc123'  # 模拟用户名密码数据库
    
    
    def auth(func):  # 登录装饰器
        def wrapper():
            username = input("UserName:").strip()
            password = input("Password:").strip()
            if user == username and passwd == password:
                print("登录成功")
                func()
            else:
                exit("验证失败!")
    
        return wrapper
    
    
    def index():
        print("wolcome to index")
    
    
    @auth  # home 被装饰(没有修改源代码和调用方式)
    def home():
        print("wolcome to home")
    
    
    @auth  # bbs被装饰(没有修改源代码和调用方式)
    def bbs():
        print("wolcome to bbs")
    
    
    index()
    bbs()
    home()

      运行结果:

    index 直接可以显示

    wolcome to index

    随后要求输入用户名和密码,登录后才能浏览home 和bbs

    UserName:dwdar
    Password:abc123
    登录成功
    wolcome to bbs
    UserName:dwdar
    Password:abc123
    登录成功
    wolcome to home

    3、通过几年的发展,网站又有了新的要求,home 这个函数需要返回值了,需要我们更新以下装饰器。

    假设home的返回值是这样的。

    @auth  # home 被装饰(没有修改源代码和调用方式)
    def home():
        print("wolcome to home")
        return "from home"  #home 需要返回值

      目前的装饰器是无法实现返回值的,我们对装饰器进行如下升级即可打印返回值了。

     1 # Author:Dwdar
     2 
     3 user, passwd = 'dwdar', 'abc123'  # 模拟用户名密码数据库
     4 
     5 
     6 def auth(func):  # 登录装饰器
     7     def wrapper(*args,**kwargs):
     8         username = input("UserName:").strip()
     9         password = input("Password:").strip()
    10         if user == username and passwd == password:
    11             print("登录成功")
    12             res = func(*args,**kwargs)
    13             return res
    14         else:
    15             exit("验证失败!")
    16 
    17     return wrapper
    18 
    19 
    20 def index():
    21     print("wolcome to index")
    22 
    23 
    24 @auth  # home 被装饰(没有修改源代码和调用方式)
    25 def home():
    26     print("wolcome to home")
    27     return "from home"  # home 需要返回值
    28 
    29 
    30 @auth  # bbs被装饰(没有修改源代码和调用方式)
    31 def bbs():
    32     print("wolcome to bbs")
    33 
    34 
    35 index()
    36 bbs()
    37 print(home())       #打印home的返回值

     4、又过了一段时间,网站又有了新变化,要求BB 用本地认证系统登录,而BBS需要ldap 认证服务器登录。这下怎么办呢?

    第一步:首选我们想到调用装饰器需要传参,通过装饰器参数来判断调用方式。调用装饰器如下。

    def index():
        print("wolcome to index")
    
    
    @auth(auth_type="local")  # 装饰器需要传参,通过参数判断登录方式
    def home():
        print("wolcome to home")
        return "from home"
    
    
    @auth(auth_type="ldap")  # 装饰器需要传参,通过参数判断登录方式
    def bbs():
        print("wolcome to bbs")

    第二步:装饰器再添加一层函数 outer_wrappr 来接收相关参数最终可以实现判断。

    完整代码如下:

    # Author:Dwdar
    '''
    有一个网址有多个页面,大部分页面时直接浏览的。比如index
    后来有了新的要求:
    要对home 和页面BBS页面登录才能预览。通过装饰器需要给home 和BBS 添加登录的功能怎么做呢?
    
    
    
    '''
    
    user, passwd = 'dwdar', 'abc123'
    bbsuser, bbspasswd = 'bbs', 'bbs123'  # 模拟ldap 认证账号
    
    
    def auth(auth_type):
        # print("auth func:", auth_type)
    
        def outer_wrappr(func):
            def wrapper(*args, **kwargs):
                # print("wrapper func arges:", *args, **kwargs)
                if auth_type == "local":
                    username = input("UserName:").strip()
                    password = input("Password:").strip()
                    if user == username and passwd == password:
                        print("登录成功")
                        res = func(*args, **kwargs)
                        return res
                    else:
                        exit("验证失败!")
                elif auth_type == "ldap":
                    username = input("bbsUserName:").strip()
                    password = input("bbsPassword:").strip()
                    if bbsuser == username and bbspasswd == password:
                        print("登录成功")
                        res = func(*args, **kwargs)
                        return res
                    else:
                        exit("BBS验证失败!")
    
            return wrapper
    
        return outer_wrappr
    
    
    def index():
        print("wolcome to index")
    
    
    @auth(auth_type="local")  # 装饰器需要传参,通过参数判断登录方式
    def home():
        print("wolcome to home")
        return "from home"
    
    
    @auth(auth_type="ldap")  # 装饰器需要传参,通过参数判断登录方式
    def bbs():
        print("wolcome to bbs")
    
    
    index()
    bbs()
    print(home())

    运行结果:

    wolcome to index
    bbsUserName:bbs
    bbsPassword:bbs123
    登录成功
    wolcome to bbs
    UserName:

    通过判断登录BBS需要输入用户名:BBS的账号和密码才能进入。

  • 相关阅读:
    HTTP请求报文与响应报文
    RTTI (Run-time type information) in C++
    Advanced C++ | Virtual Copy Constructor
    Virtual Destructor
    Advanced C++ | Virtual Constructor
    What happens when more restrictive access is given to a derived class method in C++?
    Can static functions be virtual in C++?
    Virtual functions in derived classes
    Default arguments and virtual function
    Multiple Inheritance in C++
  • 原文地址:https://www.cnblogs.com/dwdar/p/11691256.html
Copyright © 2011-2022 走看看