赣州网站建设精英,做动态图片的网站,聊天app开发源码,网站的目标装饰器概念装饰器本质上是一个python函数#xff0c;它可以让其他函数在不需要做任何代码变动的前提下增加额外功能#xff0c;装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景#xff0c;比如#xff1a;插入日志、性能测试、事务处理、缓存、权限验证等场景…装饰器概念装饰器本质上是一个python函数它可以让其他函数在不需要做任何代码变动的前提下增加额外功能装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景比如插入日志、性能测试、事务处理、缓存、权限验证等场景装饰器是解决这类问题的绝佳设计有了装饰器我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲装饰器的作用就是为已经存在的对象添加额外的功能。装饰器代码实战友情提示接下来的代码有点多希望大家可以拷贝下来实际运行一下相信会对装饰器这个概念有更为深刻的理解给大家举个例子定义一个now函数 输出当前时间def now ():print(time.strftime(%Y-%m-%d-%H_%M_%S, time.localtime()))现在假设我们要增强now()函数的功能比如在函数调用前后自动打印日志但又不希望修改now()函数的定义这种在代码运行期间动态增加功能的方式称之为“装饰器”Decorator。本质上decorator就是一个返回函数的高阶函数。所以我们要定义一个能打印日志的decorator可以定义如下def log(func):def wrapper(*args, **kw):print(call start: func.__name__)func(*args, **kw)print(call end: func.__name__)return wrapper这是一个较为固定的写法参数func表示传入的函数对象wrapper是内部函数return wrapper 会实现对其调用(*args, **kw)是一种固定用法表示可以传入任意的参数*args和**kw分别属于非关键字参数和关键字参数两者也都是可变参数。一个星号*加上参数名比如*number定义后number可以接收任意数量的参数并将它们储存在一个tuple中。关键字参数的特征是两个星号**加上参数名比如**kw, 定义后kw将接收到的任意数量参数存到一个dict中。举个例子就懂了def func_para(*args, **kw):print (args:,args )print (kw:,kw )func_para(1,2,3,4, a1,b2,c3)输出args: (1, 2, 3, 4)kw: {a: 1, b: 2, c: 3}func(*args, **kw) 表示对传入的函数进行调用调用前后分别执行了两条print语句func.__name__ 表示函数的名字def wrapper 根据需求也可以return 某个值。最后调用装饰器的代码如下在now上面加上装饰器 log即可def func_para(*args, **kw):print (args:,args )print (kw:,kw )func_para(1,2,3,4, a1,b2,c3)
log
def now ():print(time.strftime(%Y-%m-%d-%H_%M_%S, time.localtime()))
now()输出call start:now2023-03-10-15_08_40call end:now看到这里有的同学可能会问如果now()函数需要增加参数怎么办很简单我们无须对装饰器log进行任何修改代码如下log
def now (a,b):print(a)print(time.strftime(%Y-%m-%d-%H_%M_%S, time.localtime()))print(b)
now(test1,test2)输出call startnowtest12023-03-10-15_08_40test2call end:now装饰器的本质其实想要了解装饰器的本质我们需要了解python的函数对象python中一切皆是对象所以函数也不例外我们还是以下面代码为例def now ():print(time.strftime(%Y-%m-%d-%H_%M_%S, time.localtime()))
print(now)
print(type(now))输出function now at 0x000001C7C5D44F78class function可以看到输出了now对象的地址和对应的类型。我们也可以理解函数的名字就是函数在内存中对应的地址我们可以把函数赋值anowprint(a)此时输出的a 的值与print(now) 是一样的!我们也可以把函数作为参数传递例如import time
def now():print(time.strftime(%Y-%m-%d-%H_%M_%S, time.localtime()))def func_demo(func):return func #调用作为参数传入的函数func1func_demo(now)
func1()输出2023-03-10-15_18_44讲到这里我们可以看出来logdef now ():其实等价于log(now)这里now作为了装饰器函数log的参数log只是语法糖而已语法糖是计算机语言中特殊的某种语法,这种语法对语言的功能并没有影响对于程序员有更好的易用性能够增加程序的可读性。大家可以结合前面讲解的def log函数的代码然后执行以下代码import time
def log(func):def wrapper(*args, **kw):print(call start: func.__name__)func(*args, **kw)print(call end: func.__name__)return wrapper
log
def now ():print(time.strftime(%Y-%m-%d-%H_%M_%S, time.localtime()))dlog(now)
d()会输出call start:wrappercall start:now2023-03-10-15_29_47call end:nowcall end:wrapper