闭包
基本概念
- 定义:在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
- 简单举例
- 情形一:内部函数在修改外部的变量前访问了该变量,则访问前必须加修饰,否则访问时会报错
- 情形二:使用 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_func
def 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_func
def test():
print('555')
test()
'''
执行结果:
333
111
222
444
555
'''
def make_bold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped
def make_italic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped
@make_bold
@make_italic
def 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_func
def f():
print(f.__name__)
f()
'''
执行结果:
func_name: f
inner_func
'''
有参数的装饰器
def outer_func(func):
def inner_func(a, b):
func(a, b)
return inner_func
@outer_func
def f(a, b):
print(a + b)
f(1, 2) # 3
f(3, 4) # 7
不定长参数的装饰器
采用 args 和 *kwargs 的参数设计,无论是有参数,无参数,还是多个参数,均能实现传递
def outer_func(func):
def inner_func(*args, **kwargs):
func(*args, **kwargs)
return inner_func
@outer_func
def 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_func
def f():
return '111'
print(f()) # None
def outer_func(func):
def inner_func():
return func()
return inner_func
@outer_func
def 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_func
return set_func
@set_level(1)
def test1():
print('111')
return 'aaa'
@set_level(2)
def test2():
print('222')
return 'bbb'
print(test1())
print(test2())
'''
执行结果:
AAA
111
aaa
BBB
222
bbb
'''