装饰器
前言:
装饰器的作用是什么?直白了说就是给一个方法或者类,在其原有的功能上添加新的功能。
一、闭包
概念:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包。
来看一个例子:
def outer(x): def inner(y): sum_t = x + y return sum_t return inner o = outer(3) result = o(4) print(result)
分析:
1.outer函数与inner函数嵌套。
2.内部函数引用了外部作用域的变量x。
3.外部函数返回了内部函数名(返回内部函数的引用,是python的特色之一)。
当调用了外部函数outer之后,获得的是内部函数的引用,然后调用内部函数(使用括号),即可执行内部函数的代码。
二、装饰器
要了解装饰器,必须先了解闭包,因为二者有着一定的联系。
def login(func): def wrapper(): print("this is wrapper") func() return wrapper @login def check_in(): print("this is check_in") check_in()
执行结果:
this is wrapper this is check_in
我们可以看到,当check_in函数杯login装饰之后,执行check_in其实是额外执行了login中新增的内容。
我们来解析一下:
当check_in被login装饰后,会自动将check_in 传入到login中,在login的wrapper中,代码是执行print语句和login函数,login将wrapper返回。
仔细看下面:
def login(func): def wrapper(): print("this is wrapper") func() return wrapper @login def check_in(): print("this is check_in") print(check_in)
执行结果:
<function login.<locals>.wrapper at 0x000001F97FA1EEE0>
我们可以看到,check_in 实际上是wrapper函数的引用,那么check_in() 和 wrapper() 是一模一样的。而wrapper()不仅执行了传入进来的真实的check_in(),还执行了额外的功能。
三、带参数的装饰器
def login(func): def wrapper(x): print("this is wrapper") func(x) return wrapper @login def check_in(x): print("this is check_in") print("this is x %d" % x) check_in(5)
执行结果:
this is wrapper this is check_in this is x 5
因为被装饰的check_in需要接收参数,那么就需要让装饰器的内部函数wrapper接收参数,实际上这个参数是给传入的函数引用使用的。
四、万能参数装饰器
def login(func): def wrapper(*args, **kwargs): print("额外的功能") func(*args, **kwargs) return wrapper @login def check_in(x, y=0): print("this is check_in") print("this is x %d" % x) print("this is y %d" % y) check_in(5, y=1)
执行结果:
额外的功能 this is check_in this is x 5 this is y 1
五、更为完整的装饰器:
def login(s): print("this is login") print("this is %s" % s) def inner(func): def wrapper(*args, **kwargs): print("额外的功能") func(*args, **kwargs) return wrapper return inner @login("hello python") def check_in(x, y=0): print("this is check_in") print("this is x %d" % x) print("this is y %d" % y) check_in(5, y=1)
执行结果:
this is login this is hello python 额外的功能 this is check_in this is x 5 this is y 1
结论:若需要装饰器可以接收参数,那么需要在原有的装饰器外面再套一层。
浙公网安备 33010602011771号