Python 装饰器 demo

被装饰函数的参数传递过程

from time import sleep
def decorator(func):
    return sum

@decorator
def study():
    print("我在学习……")
    sleep(2)

x = [1,2,3]
print(study(x))          # 结果为 6,不是 "我在学习……"
  1. 被装饰之后,执行 study(x) 就等于 study = decorator(study),但是 decorator 的返回值是 sum 函数,
  2. 所以最终 study 函数被装饰器修改成了 sum 函数,原来的 study 函数没有被真正调用,也不会执行。
  3. 执行被装饰过后的 study 函数的时候,其实是执行的 sum 函数,所以尽管原始study函数不接收传参,但是 sum
    函数接收参数,所以被装饰后的 study 可以接受 x 作为参数。

一个输出 log 的例子:

from time import sleep, time

def logged(when):
    from functools import wraps

    def log(func, *args, **kwargs):
        print("""Called:
    Func: %s
    args: %s
    kwargs: %s""" % (func, args, kwargs))

    def pre_logged(func):
        @wraps(func)
        # 被装饰的 func 所带的参数,是通过 wrapper 传递进去的
        def wrapper(*args, **kwargs):
            log(func, *args, **kwargs)
            return func(*args, **kwargs)
        return wrapper

    def post_logged(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            now = time()
            try:
                return func(*args, **kwargs)
            finally:
                log(func, *args, **kwargs)
                print(time()-now)
        return wrapper

    try:
        return {
            "pre": pre_logged,
            "post": post_logged, }[when]
    except KeyError as e:
        raise ValueError(e)


@logged("post")
def hello(name):
    print("Hello %s" % name)


hello(name="World")

执行结果:

Hello World
Called:
    Func: <function hello at 0x7fa872174280>
    args: ()
    kwargs: {'name': 'World'}
0.00012946128845214844

执行过程解析:

hello(name=“World”)
等价于 logged(“post”)(hello(name=“World”))
还等价于 post_logged(hello(name=“World”))

  1. hello = logged(“post”)(hello(name=“World”))
  2. logged(“post”) 返回 post_logged,变为 post_logged(hello(name=“World”))
  3. post_logged 函数执行返回 wrapper 函数,此时变为 wrapper(name=“World”)
  4. wrapper 函数中的 try 子句返回了 hello(“World”),在这里执行了原来的函数
  5. 之后 wrapper 函数中的 finally 子句,执行了 log 函数,打印出来了调用关系
  6. 最终实现的效果是:在不更改原来 hello 函数的前提下,统计了函数的执行时间

参考资料:

  1. 《Python 核心编程 第二版》
  2. https://zhuanlan.zhihu.com/p/339257343
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

某呆啊

赏个糖吃吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值