前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BAT面试题39:Python中的装饰器用过吗?

BAT面试题39:Python中的装饰器用过吗?

作者头像
double
发布2019-07-17 16:09:37
7220
发布2019-07-17 16:09:37
举报
文章被收录于专栏:算法channel算法channel

本质上,装饰器(decorator)就是一个返回函数的高阶函数。拿到一个函数,返回一个函数,或者拿到一个类,返回另一个类。

这是普通函数,组装后实现的效果:

代码语言:javascript
复制
def use_logging(func):
  print("%s is running" % func.__name__)
  return func

def bar():
  print('i am bar')

use_logging(bar)()

如果使用装饰器,可以这么做:

代码语言:javascript
复制
def use_logging(func):
  print("%s is running" % func.__name__)
  return func

@use_logging
def bar():
  print('i am bar')

bar()

以上输出,都为如下:

代码语言:javascript
复制
bar is running

i am bar

对比以上两种写法,可以看出,装饰器就是一个返回函数的高阶函数。python提供了@ 符号作为装饰器的语法糖,使我们更方便的应用装饰函数。但使用语法糖要求装饰函数必须return一个函数对象

Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。

decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。下面举一个例子:设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间。

代码语言:javascript
复制
import time
def log(func):
     def wrapper(*args,**kw):
         t1 = time.time()
         func(*args,**kw)
         print('%s excute in %s ms'%(func.__name__,1000*(time.time()-t1)))
     return wrapper


@log
def slow(x,y,z):
     time.sleep(5)

@log
def fast(x,y):
     time.sleep(2)

slow(4,5,6)
fast(3,5)

print(slow.__name__)

以上写法有些缺陷,因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错

不需要编写 wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps 就是干这个事的,所以,一个完整的decorator的写法如下:

代码语言:javascript
复制
import time,functools
def log(func):
     @functools.wraps(func)
     def wrapper(*args,**kw):
         t1 = time.time()
         func(*args,**kw)
         print('%s excute in %s ms'%(func.__name__,1000*(time.time()-t1)))
     return wrapper


@log
def slow(x,y,z):
     time.sleep(5)

@log
def fast(x,y):
     time.sleep(2)

slow(4,5,6)
fast(3,5)

print(slow.__name__)

以上就是装饰器的主要用法,你还知道它的哪些主要应用,欢迎留言。

参考:

https://www.liaoxuefeng.com/wiki/

https://www.cnblogs.com/hiwuchong/p/8136982.html

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员郭震zhenguo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档