- 闭包
内层函数对外层函数变量的引用,非全局变量
def f1(name):
def f2():
print('Hello', name)
return f2
ret = f1()
ret() # Hello Laura
del f1 # 删除f1函数
ret() # Hello Laura 由于f1函数内部的内容已经存到ret中,即使引用了外层函数的变量,也已经存在ret中了
f1() # NameError: name 'f1' is not defined
- 装饰器原理
def func1():
print('in func1')
def func2(func):
def func3():
print('in func3')
func()
return func3
func2(func1)()
# 运行结果
in func3
in func1
# 现在我想执行func1()就达到以上效果,于是重写赋值func1
def func1():
print('in func1')
def func2(func):
def func3():
print('in func3')
func()
return func3
func1 = func2(func1)
func1()
# 运行结果
in func3
in func1
# 为了代码简洁,python又用@函数名省去了以上步骤,这就是python中装饰器原理,如
def func2(func):
def func3():
print('in func3')
func()
return func3
@func2
def func1():
print('in func1')
func1()
运行结果:
in func3
in func1
- 装饰带参数的函数
def wrapper(func):
def inner(*args, **kwargs):
print('start')
r = func(*args, **kwargs)
print('end')
return r
return inner
@wrapper
def my_sum(x, y):
return x + y
print(my_sum(3, 8))
运行结果
start
end
11
- 装饰器本身带参数
def mk(arg):
def wrapper(func):
def inner(*args, **kwargs):
print('欢迎Vip用户进入{}专栏!'.format(arg))
func(*args, **kwargs)
return inner
return wrapper
@mk('电影')
def movie():
print('这是电影专栏')
movie() # 相当于执行了mk('电影')(movie)()
运行结果
欢迎Vip用户进入电影专栏!
这是电影专栏
- 装饰器修复技术
被装饰过的函数通过__doc__,找不到需要的函数解释,或通过__name__不能显示该函数名,因为本身不是执行此函数, 输出的是真正执行的函数名或函数简介。用@warps装饰实际的函数就可以了。
from functools import wraps
def wrapper(func):
def inner(func):
'''
inner函数
:param func:
:return:
'''
print('new affect')
func(*args, **kwargs)
return inner
@wrapper
def f1(arg1, arg2):
'''
这里写这个函数是做什么的
:param arg1:
:param arg2:
:return:
'''
print('in f1')
print(f1.__doc__) # 被装饰过的函数实际是执行的wrapper(f1)(),也就是wrapper(f1).__doc__, wrapper(f1)返回的是inner函数名,所以查看的是inner函数的内的文档,如果想查f1本身的文档,就要用wraps装饰inner函数
print(f1.__name__) # inner 同上,不能查看函数名
运行结果:
inner函数
:param
func:
:return:
inner
用wraps函数装饰;
from functools import wraps
def wrapper(func):
@wraps(func)
def inner(func):
'''
inner函数
:param func:
:return:
'''
print('new affect')
func(*args, **kwargs)
return inner
@wrapper
def f1(arg1, arg2):
'''
f1函数
:param arg1:
:param arg2:
:return:
'''
print('in f1')
print(f1.__doc__)
print(f1.__name__)
运行结果
f1函数
:param arg1:
:param arg2:
:return:
f1
- 被多个装饰器装饰
def wrapper1(func):
print('in wrapper1')
def func2():
print('in func2')
return func()
return func2
def wrapper2(func):
print('in wrapper2')
def inner():
print('in func4')
return func()
return inner
@wrapper1
@wrapper2
def f1():
return 'Hello Laura!'
f1()
运行结果
in wrapper2
in wrapper1
in func2
in func4
总结:
装饰器和python中的类性质都是定义一个模版,然后引用这个模版。新建实例化对象或装饰一个函数,实际执行的是模版最内层的函数体。装饰器实际就是指引被装饰的函数去哪里找实际执行的函数,被装饰的函数当做参数传给最外层函数。接着返回内层函数的地址,再执行他。