目录
一、装饰器的概念和意义
1、装饰器的概念
2、函数即变量
3、高阶函数
4、嵌套函数
5、编写装饰器
二、装饰器的常见类型和编写
1、被装饰函数带参数
2、装饰器本身带参数
3、被装饰函数带返回值
三、函数闭包
四、闭包和装饰器的区别
def boo():
print("in boo")
a=boo
boo() # in boo
a() # in boo
def foo():
print("in foo")
boo()
def boo():
print("in boo")
foo() # 不会报错
def foo():
print("in foo")
boo()
foo() # 会报错
def boo():
print("in boo")
def foo():
print("in foo")
def gf(func): # 高阶函数
print(func) # 运行foo函数之前附加的功能语句
func()
gf(foo)
尝试使用高阶函数统计任意函数运行时间。
import time
def foo():
print('in foo')
def gf(func):
start_time=time.time() # 记录函数开始运行的时间
func()
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
gf(foo) # 改变了foo的调用方式,不满足装饰器的第二个原则,说明其不是一个真正的装饰器
import time
def foo():
print('in foo')
def gf(func):
start_time=time.time()
return func
end_time=time.time()
print('运行func的时间为':end_time-start_time)
foo=gf(foo)
foo()
def foo():
print('in foo')
def boo():
print('in boo')
import time
def foo():
print('in foo')
def timer(func):
def gf():
start_time=time.time() # 记录函数开始运行的时间
func()
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
return gf
foo=timer(foo)
foo() # 实际调用的是gf函数
import time
def timer(func):
def gf():
start_time=time.time() # 记录函数开始运行的时间
func()
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
return gf
@timer # foo=timer(foo),Python的语法糖,一种语法简化方式
def foo():
print('in foo')
foo()
import time
def timer(func):
def gf(name):
start_time=time.time()
func(name)
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
return gf
@timer # foo=timer(foo)
def foo(name):
print('in foo',name)
#foo=gf()
foo("hhh") # gf(name)
import time
def timer(func):
def gf(*args,**kwargs): # 通过提供不定量参数来自适应被装饰函数的参数
start_time=time.time()
func(*args,**kwargs) # 不定量参数
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
return gf
@timer # foo=timer(foo)
def foo(name,age):
print('in foo',name,age)
#foo=gf()
foo("hhh",22) # gf(*args,**kwargs)
# 被装饰函数带有参数或不带参数
def deco(func):
def inner(*args,**kwargs):
# 包含所有要附加的功能
func(*args,**kwargs)
return inner
import time
def timer(timer_type):
print(timer_type)
def outer(func): # 加入一层嵌套函数,并且接受被装饰函数名作为参数
def inner(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs)
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
return inner
return outer
@timer(timer_type='minites') # foo=timer(timer_type='minites')(foo)
def foo(name,age):
print('in foo',name,age)
foo("hhh",22) # inner(*args,**kwargs)
# 装饰器本身带参数
def deco1(parma): # param是装饰器本身的参数
def outer(func): # 以被装饰的函数名作为参数
def inner(*args,**kwargs):
# 包含所有要附加的功能
func(*args,**kwargs)
return inner
return outer
import time
def timer(timer_type):
print(timer_type)
def outer(func):
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs) # 保存返回值
end_time=time.time()
print('运行func的时间为:',end_time-start_time)
return res # 返回
return inner
return outer
@timer(timer_type='minites') # foo=timer(timer_type='minites')(foo)
def foo(name,age):
print('in foo',name,age)
return name # 被装饰函数带有返回值
print(foo("hhh",22)) # inner(*args,**kwargs)
# 被装饰函数带返回值
def deco2(parma): # param是装饰器本身的参数
def outer(func): # 以被装饰的函数名作为参数
def inner(*args,**kwargs):
#包含所有要附加的功能
result = func(*args,**kwargs) # 接收到被装饰函数的返回值
return result # 返回被装饰函数的返回值
return inner
return outer
func_list = []
for i in range(3): # i=0,1,2
def myfunc(a):
return i+a # 会受外部改变的影响
func_list.append(myfunc)
for f in func_list:
print(f(1))
# 预估结果
# 1,2,3
# 实际结果
# 3,3,3
func_list = []
for i in range(3): # i=0,1,2
def deco(i): # 接收i作为参数
def myfunc(a):
return i+a #此时i为myfunc的自由变量
return myfunc # 返回myfunc函数
func_list.append(deco(i))
for f in func_list:
print(f(1))
# 预估结果
# 1,2,3
# 实际结果
# 1,2,3
装饰器 | 闭包 | |
相同的 | 1、都是函数的嵌套,分为外层函数和内层函数,而且外层函数要返回内层函数 2、代码实现的逻辑大同小异 3、二者都可以实现增加额外功能的目的 |
|
不同点 | 1、外层函数成为装饰器 2、装饰器的外层函数主要是提供被装饰函数的引用 3、装饰器的外层函数不一定要提供变量 5、从形式上看,闭包是装饰器的子集 |
1、外层函数称为闭包 2、闭包的外层函数主要是为了提供自由变量 4、闭包的目的是保存函数运行环境和局部变量值 |