写点什么

python 进阶 - 装饰器

  • 2022 年 5 月 06 日
  • 本文字数:1497 字

    阅读完需:约 5 分钟

背景

经常可以看到在一些python的函数申明前,添加了 @的标识,如下图 @tf.function 和 @app.route


这个 @就是python中的装饰器(decorater), 在这里就和大家详细说下 python 的这个特性。

什么是装饰器

python中的所有的东西都是对象,连函数也是对象,也能return; 这个是实验君最喜欢python的地方,一个函数可以返回任意你想要返回的东西(不像c/c++/java想要多个返回值,还需要废些功夫。


言归正传,装饰器是对函数的一种装饰。换句话说就是在不改变原来函数的功能基础上,给函数添加一些额外的功能,比如公共的处理,日志打印等。


举个简单的例子: 为函数的执行进行耗时统计,代码如下


def func():   start_time = time.time()   print('some function is running')   print('the running time is %s s' % (time.time()- start_time))
复制代码


如果想给不同的函数计算耗时,又不想重复的写start_time,要怎么办呢?一种解决方案是把函数作为一个参数传递给计算耗时的函数里(这似乎只有在python里可以办到吧)


def real_func1():   print('some function is running1')
def real_func2(): print('some function is running2') def time_func(func): start_time = time.time() func() print('the running time is %s s' % (time.time()- start_time))
# 执行 time_func(real_func1) time_func(real_func2)
复制代码


装饰器其实就是上面这种解决方案的一种简写。

如何构建装饰器

上面的例子怎么改写成装饰器?



def log_time() def time_func(func): start_time = time.time() func() print('the running time is %s s' % (time.time()- start_time)) return time_func
@log_timedef real_func1(): print('some function is running1')@log_timedef real_func2(): print('some function is running2')
# 执行 real_func1() real_func2()
复制代码


装饰器 log_time 就是给函数real_func1和real_func2外包了一个统计耗时的功能。


我们再看几个装饰的例子


  • 有参数的装饰器


   def log_time(func):    def make_decorater(*args, **kwargs):        print('outer print1')        test_func = func(*args, **kwargs)        print('outer print2')        return test_func    return make_decorater
@log_time def test(num): print('inner print 3') return num+1 num = test(2) print(num) # outer print1 # inner print 3 # outer print2 # 3
复制代码


  • 多个装饰器(注意执行顺序)


   def log_time1(func):    def make_decorater():        print('decorater1: outer print1')        func()        print('decorater1: outer print2')    return make_decorater
def log_time2(func): def make_decorater(): print('decorater2: outer print1') func() print('decorater2: outer print2') return make_decorater
@log_time1 @log_time2 def test(): print('inner print 3') test()
# decorater1: outer print1 # decorater2: outer print1 # inner print 3 # decorater2: outer print2 # decorater1: outer print2
复制代码

装饰器的作用

了解了装饰器的功能,聪明的你一定想到了很多装饰器的用处。就如开头提到的


  • @tf.function是把普通的函数改造成 tf 的 op 操作的函数

  • app.routeflask中普通函数封装成可以接收 http 请求的函数


总结下, 装饰器可以用来:


  • 公共日志的打印

  • 公共的模块封装,比如授权, 异常处理, 函数转换

结语

本实验和大家简单描述了python装饰器的使用,希望对大家有帮助。




发布于: 刚刚阅读数: 3
用户头像

公众号:人工智能微客(weker) 2019.11.21 加入

人工智能微客(weker)长期跟踪和分享人工智能前沿技术、应用、领域知识,不定期的发布相关产品和应用,欢迎关注和转发

评论

发布
暂无评论
python进阶-装饰器_Python_AIWeker-人工智能微客_InfoQ写作社区