小编给大家分享一下python的修饰器是什么,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!

python的修饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,修饰器的返回值是一个函数对象。

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

功能

我们首先从一个简单的例子说起,这个例子是stackflow上的一个问题,如何通过使用如下的代码实现输出<b><i>Hello</i></b>:

@makebold@makeitalicdefsay():return"Hello"

先看一下答案:

defmakebold(fn):defwrapped():return"<b>"+fn()+"</b>"returnwrappeddefmakeitalic(fn):defwrapped():return"<i>"+fn()+"</i>"returnwrapped@makebold@makeitalicdefhello():return"helloworld"printhello()#返回<b><i>helloworld</i></b>

这里的@makebold和@makeitalic似乎给Hello加上了一层包装(or修饰),这就是修饰器最明显的体现。

从需求谈起

初期,我写了一个函数

deffoo():print'infoo()'foo()

为了检查这个函数的复杂度(在网络编程中程序的延时还是很重要的),需要测算运算时间,增加了计算时间的功能有了下面的代码:

importtimedeffoo():start=time.clock()print'infoo()'end=time.clock()print'TimeElapsed:',end-startfoo()

这里只是写了一个函数,如果我想测量多个函数的延时,由于必须知道start与end,所以必须写在程序的开头与结尾,难道每一个程序都这样复制粘贴么?固然可行,但是,我们可以通过设计模式中将功能与数据部分分离一样,将这个测量时间的函数分离出去,就像C++中我们可以将这个测量时间的函数变为一个类,通过调用这个类,赋予不同的函数来测量不同的函数的运行时长。在python中,由于函数实际上就是对象,所以可以利用类似的方法实现:

importtimedeffoo():print'infoo()'deftimeit(func):start=time.clock()func()end=time.clock()print'TimeElapsed:',end-starttimeit(foo)

这里func()就可以指定函数了,但是如果我不想填这个函数或者这个功能函数并不能修改成类似的形式怎么办?我们需要的是最大限度的少改动:

importtimedeffoo():print'infoo()'#定义一个计时器,传入一个,并返回另一个附加了计时功能的方法deftimeit(func):#定义一个内嵌的包装函数,给传入的函数加上计时功能的包装defwrapper():start=time.clock()func()end=time.clock()print'TimeElapsed:',end-start#将包装后的函数返回returnwrapperfoo=timeit(foo)#可以直接写成@timeit+foo定义,python的"语法糖"foo()#在这个代码中,timeit(foo)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数,此时此foo非彼foo!因为此时的foo具有了timeit的功效,简单来说就是能够让你在装饰前后执行代码而无须改变函数本身内容,装饰器是一个函数,而其参数为另外一个函数。#一个有趣的"汉堡"让你了解顺序#顺序在修饰器还是非常重要的,利用一个代码展示一下:defbread(func):defwrapper():print"</''''''\>"func()print"<\______/>"returnwrapperdefingredients(func):defwrapper():print"#tomatoes#"func()print"~salad~"returnwrapperdefsandwich(food="--ham--"):printfoodsandwich()#输出:--ham--sandwich=bread(ingredients(sandwich))sandwich()#输出:#</''''''\>#tomatoes##--ham--#~salad~#<\______/>

加上语法糖,代码可以更简洁:

defbread(func):defwrapper():print"</''''''\>"func()print"<\______/>"returnwrapperdefingredients(func):defwrapper():print"#tomatoes#"func()print"~salad~"returnwrapper@bread@ingredientsdefsandwich(food="--ham--"):printfoodsandwich()

看完了这篇文章,相信你对python的修饰器是什么有了一定的了解,想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!