装饰器(Decorator)是 Python 中一种函数或类,用来修饰其他函数或类。装饰器可以改变被装饰函数的行为,或者在调用被装饰函数之前和之后增加额外的操作。装饰器的语法是使用 @ 语法符,在函数定义之前增加装饰器函数的名称。
@decorator_func def my_func(): pass
def decorator_func(func): def wrapper(): print("Before calling the function") func() print("After calling the function") return wrapper @decorator_func def my_func(): print("Inside the function") my_func() # Output: Before calling the function # Inside the function # After calling the function
上面展示了最简单的装饰器示例代码。在代码中,我们建立了一个名为decorator_func
的装饰器和一个名为my_func
函数。
decorator_func
时,括号中的’func’指代被装饰器装饰的函数,在这段代码中指代的就是my_func
函数。wrapper
所指定的顺序。即先执行print(“Before calling the function”);再执行func()指代的my_func函数;最后执行print(“After calling the function”)。def cal_times(func): l=[] def wrapper(*var): l.append('1') func(*var) print("函数执行了%s次"%(len(l))) return wrapper @cal_times def my_func(i): print('%s的平方是%s'%(i,i**2)) my_func(5) my_func(6)
在my_func(i)
函数中,我们增加了形参的输入,因此,在装饰器中,也要为之做出更改。此处装饰器中的wrapper函数我们使用*var
传参,这种设计方式的优点是可以让这个装饰器适用于任何函数。
再加入了cal_times
装饰器后,函数每运行一次,都会使列表l
添加一个1,这样可以计算函数的运行次数。这段代码的运行结果如下:
装饰器与函数一样,也可以带入参数,我们在第二节的基础上,对代码做出如下修改:
def decorator_func(param1, param2): def decorator(func): def wrapper(): print("Before calling the function with params:", param1,param2) func() print("After calling the function") return wrapper return decorator @decorator_func("hello", "world") def my_func(): print("Inside the function") my_func()
这段代码使用了装饰器来在my_func
函数调用前后打印额外的信息,并且装饰器函数decorator_func
接受两个参数,在调用wrapper
函数时使用这两个参数。
最终,代码将输出:
Before calling the function with params: hello world; Inside the function;After calling the function。
如果同时还有字典类型的参数传入,可以使用(*var,**_var)进行解决
前面我们定义的函数都是执行某种功能,不涉及到return的相关操作。当涉及到处理有返回值的函数时,对于内部函数我们应该使用一个变量将函数的运行结果保存起来,并放在内层函数的return中。为了实现这一功能,我们将第三部分的代码做出如下修改:
def cal_times(func): l=[] def wrapper(*var): l.append('1') result = func(*var) print("函数执行了%s次"%(len(l))) return result return wrapper @cal_times def my_func(i): print('%s的平方是%s'%(i,i**2)) return i**2 a = my_func(5) b = my_func(6) print(a,b)
对于这个装饰器,我们在内部函数wrapper
使用result保存运行结果,并将result return,这样a与b就可以被正常的赋值,运行结果如下图。
而如果不执行保存result并return,a和b将不会得到任何值: