闭包
def test(num): # test就称为闭包
def test_in(num_in): # 1、函数里面定义一个内部函数
return num+num_in # 2、内部函数使用了外部函数的形参num
return test_in # 3、返回值是一个内部函数对象test_in
ret1 = test(100) # ret1指向def test_in(num_in),即ret1为函数对象
ret1(10) # 相当于调用test_in(10)
ret1(11) # 相当于调用test_in(11)
函数装饰器
1、装饰器有2大元素,分别是:被装饰的函数、形参为“函数对象的闭包”
示例代码
def decorate(func):
def inner():
print("---开始装饰---")
func()
print("---完成装饰---")
return inner
# 方式1:
def work():
print("---work---")
work = decorate(work)
work()
# 方式2:
@decorate
def work():
print("---work---")
work()
说明: @decorate 等价于 work = decorate(work)
2、通用装饰器:装饰器的万能公式(有/无参、有/无返回值)
示例代码:有参数、有返回值的装饰器
def decorate(func):
def inner(*args,**kwargs): # 形参
print("---开始相加---")
result = func(*args,**kwargs) # 保存返回值
print("---完成相加---")
return result # return返回值
return inner
@decorate
def add1(a, b): # 形参
return a+b # 返回值
@decorate
def add2(a, b, c, d): # 形参
return a+b+c+d # 返回值
ret1 = add1(1, 2)
print("add1 = %s" % ret1)
ret2 = add2(1, 2, 3, 4)
print("add2 = %s" % ret2)
3、有形参参数的装饰器
① 假设现在已经有一个装饰器decorate,如下所示:
def decorate(func):
def inner():
if(args == "1"):
print("---开始装饰---")
func()
print("---完成装饰---")
else:
print("-------")
return inner
② 现在需要创造一个新的装饰器out_decorate,且out_decorate有形参参数,应该怎么办呢?
答案:非常简答。仅仅需要decorate外层套上一个装饰器out_decorate即可,见代码
def out_decorate(args): # 套上一层装饰器out_decorate,形参参数为args
def decorate(func):
def inner():
if(args == "param"): # args可以被使用
print("---开始装饰---")
func()
print("---完成装饰---")
else:
print("-------")
return inner
return decorate # 返回值为decorate
@out_decorate("param") # 有形参参数的装饰器
def work(): # 待装饰的函数
print("===work===")
work() # 调用
类当作装饰器
1、类对象,以函数的形式,调用__call__方法
class Test(object):
def __call__(self, *args, **kwargs): # 1、重写__call__方法
print(args)
print("-----Test Class-----")
obj = Test() # 2、创建类对象obj
obj("Tom","Lakers",20) # 3、obj("Tom","Lakers",20)本质上执行的是__call__方法
程序执行结果:
('Tom', 'Lakers', 20)
-----Test Class-----
2、类作为装饰器,装饰函数接口
# (1) 类作为装饰器,该类有4个特点
class Decorate(object):
def __init__(self,func): # 1、初始化函数,必须有一个func形参,用于接收函数对象
self.__func = func # 2、定义一个私有的__func保存接收到的函数对象func
def __call__(self, *args, **kwargs): # 3、必须重写__call__函数:当被装饰的函数执行时,调用__call__函数
print("__装饰开始__") # 装饰的内容
self.__func(*args, **kwargs) # 4、调用self.__func()函数
print("__装饰完成__") # 装饰的内容
# (2) 使用装饰器类装饰函数,即在函数之前加上@Decorate即可!
@Decorate # 等价于 test = Decorate(test) 返回值是Decorate对象
def test(a,b): # 被装饰的函数
print("---test---")
@Decorate
def test1(a,b,c):
print("---test1---")
# (3) 调用被装饰的函数:本质上调用了__call__函数
test(1,2)
test1(1,2,3) # (4) 函数的形参,都传递给了def __call__(self, *args, **kwargs)中的*args, **kwargs