一、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 = '\033[36;41mnew action\33[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)