装饰器
def out_func(func):
"""
functools.wraps 可以将原函数对象的指定属性复制个包装函数对象
"""
@functools.wraps(func)
def inner_func(func, *args, **kwargs):
return func()
return inner_func
@out_func
def foo():
print("hello,world")
装饰器概念
在不违反开放封闭的原则下,对被装饰的函数进行功能扩充
实质:闭包
带来的问题:被装饰函数名称等属性变为闭包的内函数,使用 functools.wraps 可以将原函数对象的指定属性复制个包装函数对象
Flask 中 g 变量贯穿当前的这次请求
面试中问到装饰器的时候:
- 先回答概念:不违反开放封闭原则下,对被装饰的函数进行功能扩充
- 聊到闭包,说出闭包中的概念和形式
- 说道项目中的实际使用:在 Flask 中 user 对象用到的地方很多,就单独写出来为一个装饰器,将 user 对象查询出来,放到 g 变量中
- 在 Flask 中,每个 url 对象一个函数,但是被装饰完,引用指向就变了,使用 functools.wraps 将引用指向原来的指向
闭包:
闭‘包在代码中的表现形’式
- 函数嵌套
- 内函数使用了外函数的局部变量
- 外函数返回的内函数的引用
内函数的引用和外函数被使用的局部变量构成的特殊空间——闭包
闭包的延迟绑定,当外函数准备返回内函数的引用的时候,发现内函数使用了外函数的局部变量,就将内函数引用和局部变量绑定形成特定空间,这种绑定称为延时绑定
def multipliers():
return [lambda x : i*x for i in range(4)]
print([m(2) for m in multipliers()])
# 上面的代码和下面的一样
def multipliers():
list_funcs = []
for i in range(4):
def inner(x):
return i * x
list_funcs.append(inner)
return list_funcs
print([m(2) for m in multipliers()])