python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象。装饰器函数的外部函数传入我要装饰的函数名字,返回经过修饰后函数的名字;内层函数负责修饰被修饰函数。从上面这段描述中我们需要记住装饰器的几点属性,以便后面能更好的理解:
实质: 是一个函数
参数:是你要装饰的函数名(并非函数调用,不能有括号)
返回:是装饰完的函数名(也非函数调用,不能有括号)
作用:在不改变源代码的情况下,给函数增加新的功能。
特点:不需要对对象做任何的代码上的变动。
函数也是一个对象,函数对象可以赋值给变量,所以,通过变量也可以调用该函数。
def hello(): print("Hello,world") hello() # 直接调用hello()函数 # 返回Hello,world a = hello() # a表示把hello()函数的返回值给到a a # 返回Hello,world h = hello # h是一个函数,把函数hello()赋值给一个变量 h() # 通过变量调用hello()函数 # 返回Hello,world
注意:
a = hello() 表示把hello()函数的返回值给到a a是None
h = hello b是一个函数,把hello()函数赋值给一个变量b,相当于b() = hello(),当调用b()的时候(注意b后面有括号是调用函数),就相当于调用hello()
不带参数的装饰器
现在我们想在打印Hello,world之前和之后分别打印一个start和end,但是又不希望修改hello()函数的代码,这时我们就需要用到装饰器。
装饰器的作用:在不改变源代码的情况下,给现有的函数增加新的功能。
# 构建一个装饰器
def startEnd(fun): # 相当于把hello函数传给startEnd() def wapper(): print("!!!!!!!start!!!!!!!!") fun() print("!!!!!!!end!!!!!!!!") return wapper # 函数可以作为return的返回值 # 返回值是wapper,并没有执行,当调用hello()的时候,相当于执行了wapper() # 使用装饰器
@startEnd
def hello(): print("hello") hello() # 结果 !!!!!!!start!!!!!!!! hello !!!!!!!end!!!!!!!!
注意:@startEnd 相当于 hello=startEnd(hello)
由于startEnd()是一个装饰器,返回一个函数,原来的hello()函数仍然存在,只是现在同名的hello变量指向了新的函数startEnd(),于是调用hell()将执行新的函数,即在startEnd()函数中返回的wrapper()函数。
装饰器中的return返回的是一个函数,但是是没有调用的,注意没有括号。
带参数的装饰器
# 构建一个装饰器
def startEnd(fun): def wrapper(name): print("!!!!!!!start!!!!!!!!") fun(name) print("!!!!!!!end!!!!!!!!") return wrapper # 这里,返回值是wrapper()函数
# 使用装饰器
@startEnd def hello(name): print("hello {0}".format(name)) hello("world") # 这里调用hello()函数,并传入参数,相当于执行wrapper()函数 # 结果 !!!!!!!start!!!!!!!! hello world !!!!!!!end!!!!!!!!
注意:参数先传递给wrapper(),然后wrapper()再把这个参数传递给startEnd()进行调用,wrapper()再把参数传给hello()。
装饰器中的return返回的是一个函数,但是是没有调用的,注意没有括号。
当我们在调用装饰器返回的函数的时候,其实是在调用封装函数,给封装函数传递参数也就是给被装饰的函数传递了参数。
另一个例子:
import time # 创建装饰器 def decorator(func): def wrapper(*args, **kwargs): start_time = time.time() print("开始时间:{0}".format(start_time)) func() end_time = time.time() print("结束时间:{0}".format(end_time)) return wrapper # 使用装饰器 @decorator def func(): print("Hello") # 调用函数 func() # 结果 开始时间:1524099418.73 Hello 结束时间:1524099418.73
在上面代码中,func是我要装饰器的函数,我想用装饰器显示func函数开始时间和结束时间。@decorator这个语法相当于执行 func = decorator(func),为func函数装饰并返回。再来看一下我们的装饰器函数decorator,该函数的传入参数是func(被装饰函数),返回参数是内层函数。这里的内层函数wrapper,它起到装饰给定函数的作用,wrapper参数为*args, **kwargs。*args表示的参数以列表的形式传入;**kwargs表示的参数以字典的形式传入。