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

    一、nonlocal关键词:

    • 定义:将 L 与 E(E中的名字需要提前定义) 的名字统一
    • 试用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值
    #案例:
    def outer():
        num = 10
        print(num) #10
        def inner():
            # 如果想在被嵌套的函数中修改外部函数变量的值
            nonlocal num
            num = 20
            print(num) #20
        inner()
        print(num) #20

    二、开放封闭原则:

    • 不能修改被装饰对象(函数)的源代码(封闭)

    • 不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放)

    三、装饰器:

      用途:装饰器是用来为被装饰对象添加新功能的一种工具
    • 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
    • 被装饰的函数:fn
    • 外层函数:outer(func) outer(fn) => func = fn
    • 替代版函数:return inner:原功能,新功能
    def fn():
        print('原有功能')
    
    def conter(tag):
        def inner():
            tag() 
            print('新增功能')
        return fn
    fn = conter(tag)
    fn()
    
    
    #例子
    def vase():
        print('插花')
    
    #下方函数嵌套结构就是装饰器
    def wrap(tag):
        def fn():
            tag() # 原来的vase
            print('绘画:进行观赏')
        return fn # 拓展功能后的vase
    vase = wrap(vase) #将拓展功能后的功能函数重新赋值给vase
    vase() #功能拓展了,且调用方式不变
    View Code
    • @语法糖:@外层函数
    def outer(fn):
        def inner():
            fn()
            print('新增功能1')
        return inner
    
    def wrap(fn):
        def inner():
            fn()
            print('新增功能2')
        return inner
    
    @wrap
    @outer  #<==> vase = outer(vase)
    def vase():
        print('原有功能')
    
    vase()
    View Code
    • 有参有返的函数被装饰
    def check_usr(fn):  # fn,login,inner:不同状态下的login,所以参数是统一的
        def inner():
            #在原有功能上添加新功能
            
            #原有功能
            result = fn(usr,pwd)
            #在原有功能下添加新功能
            #...
            return result
        return inner
    
    @check_usr
    def login (usr,pwd):
        if usr == 'abc' and pwd == '123qwe':
            print('登陆成功')
            return True
        print('登录失败')
        return False
    #总结:
    #1、login有参数,所以inner与fn都相同参数
    #2、login有返回值,所以inner与fn都有返回值
    View Code
    • 装饰器公式最终写法:
    def wrap(fn):
        def inner(*args,**kwargs):
            print('前增功能')
            result = fn(*args,**kwargs)
            print('后增功能')
            return result
        return inner
    
    @wrap
    def fn1():
        print("fn1的原有功能")
    
    def fn2(a,b):
        print("fn2的原有功能")
    
    def fn3():
        print("fn3的原有功能")
        return True
    
    def fn4(a,*,x):
        print("fn4的原有功能")
        return True
    
    fn1()
    fn2(10,20)
    fn3()
    fn4(10,x=20)
    View Code
    • 带参装饰器:
    # 了解
    def outer(input_color):
        def wrap(fn):
            if input_color == 'red':
                info = '33[36;41mnew action33[0m'
            else:
                info = 'yellow:new action'
    
            def inner(*args, **kwargs):
                pass
                result = fn(*args, **kwargs)
                print(info)
                return result
            return inner
        return wrap  # outer(color) => wrap
    
    
    color = input('color: ')
    @outer(color)  # @outer(color) ==> @wrap  # func => inner
    def func():
        print('func run')
    
    func()
    View Code
    四、为什么要用装饰器?
    • 丰富了原有函数的功能

    • 提高了程序的拓展性

     

    def wrap(fn):    def inner(*args,**kwargs):        print('前增功能')        result = fn(*args,**kwargs)        print('后增功能')        return result    return inner
    @wrapdef fn1():    print("fn1的原有功能")
    def fn2(a,b):    print("fn2的原有功能")
    def fn3():    print("fn3的原有功能")    return True
    def fn4(a,*,x):    print("fn4的原有功能")    return True
    fn1()fn2(10,20)fn3()fn4(10,x=20)

  • 相关阅读:
    《汇编语言》- 来自底层的较量
    《深入理解java虚拟机》
    《深入理解java虚拟机》
    PHP进阶,使用交互模式进行快速测试实验?
    为什么要拒绝使用大事务进行处理任务?
    一份从0到1的java项目实践清单
    怎样在mybatis里向mysql中插入毫秒数的时间?
    mysql技能提升篇
    如何快速成长?我的java之路!
    微软职位内部推荐-Senior Development Engineer
  • 原文地址:https://www.cnblogs.com/wangyisen/p/10643471.html
Copyright © 2011-2022 走看看