装饰器在python面试里是你们必须迈过去的一道坎儿,在面试中非常常见。而且,在实际项目中,python装饰器也是一个非常有意和有用的功能,可以在不改变函数代码和调用方式的情况下给函数添加新的功能,广泛应用于权限校验、性能统计、日志打印等应用场景。本文会深入浅出的帮助大家理解装饰器,击破面试难点。
01
装饰器的由来
试想这样一种场景,当需要对某一些函数做耗时统计时怎么办?是在每一个函数的开头和结束各打印一个时间戳么?要是有几百函数怎么办?要是要修改计算的精度怎么办?ctrl+cctrl+v到山无棱么?有没有什么办法可以不侵入函数体,同时又代价最低呢,这个时候就需要使用到我们本文所讲到的装饰器。
02
基本概念
在理解装饰器之前,我们首先需要了解几个概念。
函数
在python里,一切皆对象,函数也是一个对象。函数名其实就是指向一段内存空间的地址。因此函数可以作为参数,也可以作为返回值。
嵌套函数
在函数体内又重新定义一个新的函数,称为嵌套函数。外部的我们叫它外函数,内部的我们叫他内函数。如下图就是一个嵌套函数,在outer的函数体内又定义了内函数inner。需要注意点一点是,当内函数在自己作用域内无法找到局部变量时,会向上一层作用域查找。具体的作用域相关的知识点在这里不详细介绍。
defouter():
a=1
definner():
b=a+1
print(b)
inner()outer()
#输出结果2
闭包
闭包是Python编程一个非常重要的概念。如果一个外函数中定义了一个内函数,且内函数体引用了外函数变量,同时外函数通过return返回内函数的引用时,会把定义时涉及到的外部引用变量和内函数打包成一个整体(闭包)返回。如下例。
defouter(out_param):
a=out_param
definner(inner_param):
b=inner_param
print(a+b)
returninner
func=outer(1)#返回inner函数对象+局部变量1(闭包)
func(10)#相当于inner(10)。输出11
03
装饰器
有了上面的基础,就比较好理解装饰器。装饰器本质上是一个嵌套函数,它接受被装饰的函数(func)作为参数,并返回一个包装过的函数。通过这种方式扩展功能,主要有2个特点:a、不修改被装饰函数的调用方式;b、不修改被装饰函数的源代码。
无参装饰器
如下例通过
符号,实现嵌套函数的调用,记录函数执行时间。importtime
defouter(func):#将test的地址传递给func
definner():
start_time=time.time()
func()#func入参数是test函数对象地址
end_time=time.time()
print(运行时间为%s%(end_time-start_time))
returninner#返回inner的地址
outer#这里实际执行的是test=outer(test)deftest():
time.sleep(10)
print(testfordecorator)
test()
#输出
#testfordecorator
#运行时间为4.
有参装饰器
通过*args和**kwargs,实现参数传递
importtimedefouter(func):#将test的地址传递给funcdefinner(*args,**kwargs):start_time=time.time()func(*args,**kwargs)#func入参数是test函数对象地址end_time=time.time()print(运行时间为%s%(end_time-start_time))returninner#返回inner的地址
outerdeftest(sleep_time):time.sleep(sleep_time)print(testfordecorator)test(2)#输出
#testfordecorator
#运行时间为2.
类装饰器
装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法(Python中,只要在创建类型的时候定义了__call__()方法,这个类型就是可调用的),当使用
形式将装饰器附加到函数上时,就会调用此方法。classFoo(object):def__init__(self,func):self._func=funcdef__call__(self):print(classdecoratorrunning)self._func()print(classdecoratorending)
Foo#实际调用方式为:bar=Foo(bar)defbar():print(bar)bar()
#输出#classdecoratorruning#bar#classdecoratorending
04
思考题
如果有多个装饰器的情况下执行顺序是怎样的呢?
求职礼包
《届互联网名企最新校招信息汇总》《套精选求职简历模板,只为免费送你》求职面经
《校招凉面-今日头条京东算法岗面经》《校招热面-渣渣学长给学弟学妹的求职建议》《职场-互联网上班公司名单-不要》《爆尿-互联网公司福利大比拼》