求职简历模板

首页 » 常识 » 诊断 » 面试题解什么是python装饰器
TUhjnbcbe - 2024/10/7 8:17:00

装饰器在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

思考题

如果有多个装饰器的情况下执行顺序是怎样的呢?

求职礼包

《届互联网名企最新校招信息汇总》《套精选求职简历模板,只为免费送你》求职面经

《校招凉面-今日头条京东算法岗面经》《校招热面-渣渣学长给学弟学妹的求职建议》《职场-互联网上班公司名单-不要》《爆尿-互联网公司福利大比拼》

1
查看完整版本: 面试题解什么是python装饰器