首先咱们要知道在python,一切皆对象,函数也是一个对象 python
>>> def test(): ... return "Hello World"
有本身的id值,有type,有本身的值app
>>> id(test) 140155005410568 >>> type(test) <class 'function'> >>> test <function test at 0x7f78614f9d08>
甚至能够赋值给其余变量函数
>>> test1 = test >>> test1() 'Hello World'
哪怕是当作参数传递给别的函数,也能够当作函数的返回值网站
>>> def foo(func): ... print(func) ... return func ... >>> test2 = foo(test) <function test at 0x7f78614f9d08> >>> test2() 'Hello World'
装饰器本质其实就是一个函数, 可让其它函数不改动源代码的状况下增长其余新功能, 好比网站常常须要的权限校验等场景code
def add(x, y): print(x+y) add(1,2)
如今咱们有一个新需求, 计算代码执行时间orm
import time def add(x, y): start_time = time.time print(x+y) stop_time = time.time print("{func} spend {time} ".format(func = "add", time = stop_time-start_time)) add(1,2)
咱们固然能够这么写, 可是一来修改了源代码可能会形成一些未知的错误, 二来若是咱们有一百个函数, 这样写也不现实, 这就是咱们装饰器出场的时候了.对象
import time def timmer(func): """ :param func: 被装饰的函数 :return: 一个计算函数运行时间的函数 """ def wrapper(*args, **kwargs): """ :param args:收集被装饰函数的参数 :param kwargs:收集被装饰函数的关键字参数 :return: """ start_time = time.time() # 让进程睡一秒 time.sleep(1) # 调用被装饰的函数 result = func(*args, **kwargs) stop_time = time.time() print("{func} spend {time} ".format(func = "add", time = stop_time-start_time)) return result return wrapper
def add(x, y): print(x,y) # 由于timmer返回的是wrapper函数对象,因此执行add()至关于执行wrapper() add = timmer(add) add(1,2)
@timmer def add(x, y): print(x,y) add(1,2)
这就是最基本的装饰器, 在不修改源代码的前提下为函数添加一个新功能, 调用时只须要在原函数上方添加一个 @deco_name , 在这里是@timmer进程
python还容许咱们给装饰器带上函数io
import time def timmer(flag): """ :param flag: 接收装饰器的参数 :return: """ def outer_wrapper(func): """ :param func: 接收被装饰的函数 :return: """ # 接收被装饰函数的参数 def wrapper(*args, **kwargs): """ :param args: 收集被装饰函数的参数 :param kwargs: 收集被装饰函数的关键字参数 :return: """ if flag == "true": start_time = time.time() # 调用被装饰的函数 result = func(*args, **kwargs) # 让进程睡一秒 time.sleep(1) stop_time = time.time() print("{func} spend {time} ".format(func="add", time=stop_time - start_time)) return result else: print("Unexpected ending") return wrapper return outer_wrapper
所谓的语法糖即是你不使用也能够完成任务,可是使用它可让你的代码更简洁function
@timmer(flag="false") def add(x, y): print(x, y) add(1,2)
当函数被多个装饰器装饰时,从里向外装饰
@a @b @c def func(): pass
至关于
func = a(b(c(func)))