前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python套路-函数式编程之装饰器

python套路-函数式编程之装饰器

原创
作者头像
用户8832503
发布2022-03-02 13:41:30
2360
发布2022-03-02 13:41:30
举报
文章被收录于专栏:php编辑php编辑

装饰器是Python非常重要的高级特性之一。装饰器的威力在于无需修改已有代码即可为程序添加新功能。

装饰器如何使用,首先我们来看一个例子。

例子一:用装饰器实现计算一个函数的执行时间。

代码语言:javascript
复制
#!/usr/bin/env python
import time
def calcTime(func):
    def wrapper(num):
        startTime = time.time()
        func(num)
        endTime = time.time()
        interval = endTime - startTime
        print('Time interval:%f secs' % intarval)
    return wrapper
@calcTime
def timeTest(num):
    print('timeTest start')
    print('sleep %d second...' % num)
    time.sleep(num)
    print('timeTest end')
    
timeTest(1)

执行结果:

代码语言:javascript
复制
timeTest start
sleep 1 second...
timeTest end
Time interval:1.001107 secs

说明:

  • 当被装饰的函数timeTest()有参数时,可将装饰器的内嵌函数wrapper修改为被装饰函数的形式即可。此时,timeTest(1)相当于calcTime(timeTest(1))

带参数的装饰器

假设想要使用共同的装饰器来修饰多个不同的函数, 则这些不同的函数参数形式不同,装饰器可以通过可变参数 (* args, **kwargs)的方式实现内嵌函数。

那么,对于装饰器本真带参数的情况,这里举一个例子。

例子二:为装饰器添加一个bool变量,通过变量的真假判断是否调用计时器功能。

代码语言:javascript
复制
#!/usr/bin/env python
import time
def calcTime(flag = False):
    if flag:
        def _calcTime(func):
            def wrapper(num):
                startTime = time.time()
                func(num)
                endTime = time.time()
                interval = endTime - startTime
                print('Time interval:%f secs' % interval)
            return wrapper
    else:
        def _calcTime(func):
            return func
    return _calcTime
@calcTime(False)
def timeTest1():
    print('timeTest1 start')
    print('sleep 1 second...')
    time.sleep(1)
    print('timeTest1 end')
@calcTime(True)
def timeTest2(num):
    print('timeTest2 start')
    print('sleep %d second...' % num)
    time.sleep(num)
    print('timeTest2 end')
    
timeTest1()
print()
timeTest2(2)

执行结果:

代码语言:javascript
复制
timeTest1 start
sleep 1 second...
timeTest1 end

timeTest2 start
sleep 2 second...
timeTest2 end
Time interval:2.002649 secs

说明:

  • 将同一个装饰器 calcTime 用于两个不同的函数:timeTest1()和timeTest2(num) , 一个没有参数, 一个有参数。
  • 通过装饰器的参数可以为装饰过程添加判断,@calcTime(True)表示进行计时,@calcTime(False)不会进行计时。

装饰器调用顺序

如果使用多个装饰器修饰同一函数时,装饰器的调用顺序怎样呢?

例子三:

代码语言:javascript
复制
#!usr/bin/env python
def dec1(func):
    print('dec1')
    def wrapper():
        print('dec1_wrapper')
        func()
    return wrapper
def dec2(func):
    print('dec2')
    def wrapper():
        print(dec2_wrapper)
        func()
    return wrapper
@dec1
@dec2
def testFunc():
    print('testFunc')
    
testFunc()

执行结果:

代码语言:javascript
复制
dec2
dec1
dec1_wrapper
dec2_wrapper
testFunc

说明:

  • 通过运行结果可以看出, 装饰器的调用顺序与语法糖@ 的声明顺序相反。
  • 以上程序中的testFunc,相当于dec1(dec2(testFunc))。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 带参数的装饰器
  • 装饰器调用顺序
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档