闭包
基本概念
- 定义:在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
- 简单举例

- 情形一:内部函数在修改外部的变量前访问了该变量,则访问前必须加修饰,否则访问时会报错

- 情形二:使用 nonlocal 修饰外部函数的局部变量,然后可以访问和修改

- 注意:外部函数的形参也是用 nonlocal 修饰

- 情形三:使用 global 修饰外部函数外的全局变量,然后可以访问和修改
装饰器
基本概念
- 开放封闭原则:已经实现的功能代码不允许被修改,但可以被扩展
- 开放:对扩展开放
- 封闭:对已实现的功能代码封闭
- 简单举例

- 上面的@outer_func其实就是将下面的函数 f 塞进函数 outer_func 中,将返回的函数 inner_func 再重新赋值给 f,等价于

- 装饰器在调用函数之前,已经被Python解释器执行了,所以在调用函数之前已经修饰好了,只需要调用即可
- 注意:如果代码在闭包内的外部函数和内部函数之间,则该部分代码在装饰函数时就已经得到了执行,而不是调用的时候
多个装饰器装饰同一个函数
规律:离得近的先装饰,离得远的后装饰,先装饰的后执行
def first_outer_func(func):print('111')def first_inner_func(*args, **kwargs):print('222')return func(*args, **kwargs)return first_inner_funcdef second_outer_func(func):print('333')def second_inner_func(*args, **kwargs):print('444')return func(*args, **kwargs)return second_inner_func@first_outer_func@second_outer_funcdef test():print('555')test()'''执行结果:333111222444555'''
def make_bold(fn):def wrapped():return "<b>" + fn() + "</b>"return wrappeddef make_italic(fn):def wrapped():return "<i>" + fn() + "</i>"return wrapped@make_bold@make_italicdef test():return 'hello-world'print(test())'''执行结果:<b><i>hello-world</i></b>'''
装饰器的分类
无参数的装饰器
def outer_func(func):def inner_func():print('func_name: %s' % func.__name__)func()return inner_func@outer_funcdef f():print(f.__name__)f()'''执行结果:func_name: finner_func'''
有参数的装饰器
def outer_func(func):def inner_func(a, b):func(a, b)return inner_func@outer_funcdef f(a, b):print(a + b)f(1, 2) # 3f(3, 4) # 7
不定长参数的装饰器
采用 args 和 *kwargs 的参数设计,无论是有参数,无参数,还是多个参数,均能实现传递
def outer_func(func):def inner_func(*args, **kwargs):func(*args, **kwargs)return inner_func@outer_funcdef f(num, *args, **kwargs):print(num)print(args)print(kwargs)print()f(1)f(3, 4, 5)f(7, 8, 9, 10, 11, a=100, b=200)'''执行结果:1(){}3(4, 5){}7(8, 9, 10, 11){'a': 100, 'b': 200}'''
带有return的装饰器
为了让装饰器更通用,一般情况下加上return
def outer_func(func):def inner_func():func()return inner_func@outer_funcdef f():return '111'print(f()) # None
def outer_func(func):def inner_func():return func()return inner_func@outer_funcdef f():return '111'print(f()) # 111
带有外部变量的装饰器
def set_level(level_num):def set_func(func):def call_func():if level_num == 1:print('AAA')elif level_num == 2:print('BBB')return func()return call_funcreturn set_func@set_level(1)def test1():print('111')return 'aaa'@set_level(2)def test2():print('222')return 'bbb'print(test1())print(test2())'''执行结果:AAA111aaaBBB222bbb'''
