zoukankan      html  css  js  c++  java
  • 函数__装饰器

    一.装饰器。

    一.装饰器.

     装饰器: 在目标函数前和后插入一段新的代码,不改变原来的代码.装饰器是对原来基础功能的扩展和开放,又不变动原代码,所以比较安全.

    装饰器的本质是一个闭包。什么是闭包,就是内层函数对外层函数的变量的引用。

    装饰器语法

    # 通用装饰器写法:
    # python里面的动态代理.
    # 存在的意义: 在不破坏原有函数和原有函数调用的基础上. 给函数添加新的功能
    def wrapper(fn): #  fn是目标函数.
        def inner(*args, **kwargs): # 为了目标函数的传参
            '''在执行目标函数之前.....'''
            ret = fn(*args, **kwargs) # 调用目标函数, ret是目标函数的返回值
            '''在执行目标函数之后....'''
            return ret  # 把目标函数返回值返回. 保证函数正常的结束
        return inner
    
    @wrapper  # target_func = wrapper(target_func) #此处的wrapper 一定记住:是不加括号的,不是调用!!!
    def target_func():
        pass
    
    # target_func = wrapper(target_func) # 此时fn就是target_func
    target_func() # 此时执行的是inner
    def outer(a):
        b = 1
        def inner():
            print(a + b)
        return inner  
    # 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数
    if __name__ == '__main__':
    inner
    = outer(1) inner()
    下面是简易版装饰器
    def
    play(username, password): print("双击lol") print("登录", username, password) print("选择狂战士") print("进草丛") return "月之光芒" def xiaoxiaole(qq): print("登录qq账号") print("消消乐") def wrapper(fn): # fn = play def inner(*args, **kwargs): # 无敌传参 接受到的是元组 ("alex", 123) print("开挂") ret = fn(*args, **kwargs) # 接受到的所有参数. 打散传递给正常的参数 return ret 接收函数的返回值 return inner play = wrapper(play) # play = inner ret = play('alex',"123") print(ret) 输出结果: 开挂 双击lol 登录 alex 123 选择狂战士 进草丛 月之光芒

    带参数的装饰器(装饰器的开关).

    def wrapper_out(flag): # 装饰器本身的参数
        def wrapper(fn): # 目标函数
            def inner(*args, **kwargs): # 目标函数执行需要的参数
                if flag == True:  #如果开关为False,就不进行函数的装饰
                    print("问问金老板. 行情怎么样啊") #执行函数之前
                    ret = fn(*args, **kwargs) # 在执行函数本身
                    print("金老板骗我. 恨你") #执行函数之后
                    return ret
                else:
                    ret = fn(*args, **kwargs)  #执行函数本身
                    return ret
            return inner
        return wrapper
    
    
    # 语法糖 @装饰器
    @wrapper_out(True) # 先执行wrapper_out(True) 返回一个装饰器   再和@拼接  @装饰器
    def yue(): # 被 wrapper装饰
        print("走啊. 约不?")
    
    yue()
    解释1:
    不理解为何会变?:
    写完一个函数之后,不指定对象的调用它,你print这个函数,打印出来的内容,除了函数里的,一定还有它自己的返回值,说白了,此时的调用完之后,函数已经变成了它自己的返回值
    解释2:
    此时,这里变成了@wrapper,是个语法糖,就是python设计的语法上的简写,他和后面定义的函数,合在一起等值于  b=wrapper(b)(此时的函数名b就等于inner函数名,再调用就是调用的inner()函数)
    解释3:
    如果这里的参数True改为False,那么就无法执行该函数,会报错,这里的Alex(True)是让函数正常执行,执行完了,会变成该函数的返回值 → wrapper,而@wrapper下面定义的函数意味着,就是wrapper函数括号里参数,
    而你再用这个参数名接收返回值,该函数名就变成了返回值,你之后再调用的实际是装饰器内部的函数,如果你想关闭装饰器,就把True,改为Flase,就可以了

    装饰器的应用:

    # 装饰器在登陆验证方面的应用.
    flag =False   #没登陆的状态为False
    def login():   #此函数为登陆函数,只有登陆成功,才会显示成功登陆的状态(flag = True)
        global flag
        zhanghao =input("请输入账号:")
        mima = input("请输入密码:")
        if zhanghao=="alex" and mima=="123":
            flag = True
            return "登陆成功"
        else:
            print("对不起,输入有误.")
            exit()
    def zhuangshi1(a):
         def zhuangshi(fn):  #装饰器函数
            def inner(*can1,**can2):
                    while 1:
                        if flag == True:
                            print("装饰器把你装饰了一番,你NB了")
                            ret = fn(*can1,**can2)
                            return ret,"从此人生达到巅峰!" #此处有多个返回值,会变成元组形式返回
                        else:
                            print("对不起,您还没登陆.")
                            login()
            return inner
         return zhuangshi
    @zhuangshi1(True)
    def wangzhe(a,b):
        print("玩家",a,"进入了游戏")
        return "得到月之光芒剑"
    a = wangzhe("alex","123456")
    print(a)
    打印结果为:
    对不起,您还没登陆.
    请输入账号:alex
    请输入密码:123
    装饰器把你装饰了一番,你NB了
    玩家 alex 进入了游戏
    ('得到月之光芒剑', '从此人生达到巅峰!')

     多个装饰器装饰同一个函数:

    def wrapper1(fn):
        def inner(*args, **kwargs):
            print("装饰1111111")
            ret = fn(*args, **kwargs)
            print("装饰1111111")
            return ret
        return inner
    
    def wrapper2(fn):
        def inner(*args, **kwargs):
            print("装饰2222222")
            ret = fn(*args, **kwargs)
            print("装饰2222222")
            return ret
        return inner
    
    #就近原则
    @wrapper1 #后被它装饰
    @wrapper2 #先被此装饰器装饰
    def func():
        print("我是幸运的func")
    func()
    输出结果为:
    装饰1111111
    装饰2222222
    我是幸运的func
    装饰2222222
    装饰1111111

    def wrapper_out(flag): # 装饰器本身的参数    def wrapper(fn): # 目标函数        def inner(*args, **kwargs): # 目标函数执行需要的参数            if flag == True:                print("问问金老板. 行情怎么样啊")                ret = fn(*args, **kwargs) # 在执行目标函数之前                print("金老板骗我. 恨你")                return ret            else:                ret = fn(*args, **kwargs)  # 在执行目标函数之前                return ret        return inner    return wrapper

    # 语法糖 @装饰器@wrapper_out(True) # 先执行wrapper_out(True) 返回一个装饰器   再和@拼接  @装饰器def yue(): # 被 wrapper装饰    print("走啊. 约不?")
    yue()

  • 相关阅读:
    【jQuery 分页】jQuery分页功能的实现
    【jQuery 使用】 利用jQuery.prop("outerHTML")获取包含自身在内的HTML元素的HTML代码
    Openfire 是怎么存离线消息
    openfire过滤脏话插件,控制消息是否发送
    openfire升级指南
    openfire教程网
    redis web 客户端工具 redis-admin
    敏捷开发Nutz
    openfire消息通知推送
    一步步教你实现跨游览器的颜色选择器
  • 原文地址:https://www.cnblogs.com/lgw1171435560/p/10118794.html
Copyright © 2011-2022 走看看