Python装饰器
函数调用加括号和不加括号的区别
- 不带括号的函数。调用的结果是返回一个函数对象,不需要等待该函数执行完成
- 带括号的函数,调用的结果是返回一个值,返回return的值,如果没有return则返回一个None。必须要等待函数执行完成
def foo(): print("ffffff") return "aaa" #不带括号的函数。调用的结果是返回一个函数对象,不需要等待该函数执行完成 print(foo) #带括号的函数,调用的结果是返回一个值,返回return的值,如果没有return则返回一个None。必须要等待函数执行完成 print(foo())
装饰器
装饰器定义
- 装饰器是Python的一种语法糖,本质是一个可调用的对象,其参数是一个被装饰的函数。装饰器可能会处理被装饰的函数并返回,或者将其替换成另一个函数或对象
- 语法糖是什么呢?
语法糖指的是计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用;可以使用这种语法增加程序的可读性,从而减少程序代码出错的可能。
装饰器条件:
- 装饰器本质上是个可调用的函数,它的参数是一个函数对象(被装饰的函数)
- 装饰器函数的定义写在被装饰的函数之前
- 怎么使用装饰器呢?在被装饰的函数前一行写@装饰器函数名
装饰器例子
- 1、写一个简单的例子,没有返回值,只打印一句“这是一个函数**”
- 2、增加需求,记录下函数的执行日志,在代码中添加日志代码
- 3、重新定义一个函数:专门处理日志,日志处理完之后再执行真正的业务代码
#未添加装饰器 def foo(): print("this is a func, foo") #执行foo函数体 #print("foo is running") #传入函数对象func def log(func): print("{} is running".format(func)) #打印日志 func() #调用func() log(foo) #加入装饰器实现上述功能 def log2(func): print("{} is running".format(func)) return func @log2 #装饰器-----#先执行装饰器函数(打印日志),返回func函数对象; def foo2(): #调用函数 print("this is a func, foo2") foo2()
装饰器何时执行
- 装饰器在被装饰的函数定义之后立即执行(即Python加载模块的时候)
#定义一个列表 registry = [] #定义一个函数,传入一个参数(函数对象) def register(func): print("register is ",func) #把函数对象存入regitry列表中 registry.append(func) #返回一个函数对象 return func @register def f1(): print("f1") @register def f2(): print("f2") def f3(): print("f3") if __name__ == '__main__': print("running main()") print("regitry->",registry) f1() f2() f3()
打印结果:
装饰器的两种用法
- 原封不动返回被装饰函数(如上面例子所示)
- 把被装饰函数替换成新函数
- 大多数装饰器,通常内部会定义一个闭包结构的函数,将其返回替换被装饰函数,用于不修改原函数的基础上增加额外的功能
闭包函数
一般是在装饰器中使用的
闭包函数满足三个条件:
- 在一个外函数中定义了一个内函数,
- 内函数里运用了外函数的临时变量,
- 并且外函数的返回值是内函数的引用,这样就构成了一个闭包
#闭包函数——outer是外部函数,a和b都是外部函数的临时变量 def outer(a): b=10 #inner是内函数 def inner(): #在inner中用到了外函数的临时变量 print(a+b) #outer外函数得到返回值是内函数的引用 return inner
把被装饰函数修饰成一个新函数
def log2(func): def log(a,b): print("{} is running".format(func)) func(a,b) return log @log2 def foo2(a,b): print("this is a func, foo2") print(a+b) foo2(1,2)