美文网首页《Django By Example》
Python - 学习理解带参数的装饰器

Python - 学习理解带参数的装饰器

作者: 思考的虫子 | 来源:发表于2020-02-13 19:19 被阅读0次

理解带参数的装饰器

参考文章 Python精进-装饰器与函数对象

加了装饰器这段代码从一个函数定义(不会执行任何东西,在内存单元中保存一段代码)变成了一条赋值语句(修改被装饰函数所在内存单元中的内容)exit

  1. 从运维角度看是装饰器补充了函数的功能, 从开发角度看是装饰器将函数作为参数
  2. 函数返回的函数无法被直接调用,除非将其返回值赋值个一个变量;列表就相当于这个函数,他的元素必须通过带参数执行这个函数获得。
  3. 该用函数还是装饰器,可以看是谁调用谁,从参数传递的方向也可以判断。

第一步: 定义装饰函数

def foo(a):
    def decorator(func):
        def wrap(*args):
            if not callable(a):
                print(a)
            return func(*args)
        return wrap
    if callable(a):
        return decorator(a)
    return decorator

# 装饰器带参数可以使得被装饰函数的改变有两种可能

第二步:使用装饰器装饰函数,调用新函数

第一种可能用法

@foo('hello')
def bar(c):
    print(c)
    return 0

装饰器的处理过程

装饰的作用是获得一个新函数

  • bar = foo('hello')(bar)
  • 先执行 foo('hello') 得到 decorator 函数
  • 然后让decorator 函数带着(bar) 一起飞
  • 就变成了 bar = decorator(bar)
  • decorator(bar) 执行得到一个函数 wrap(名字不重要,为了得到内存中的地址而已)
  • 这个新函数可以有多个参数(因为原函数带参数,装饰后也要带参数啊)
  • 额外多说一句,函数里定义的函数是可变的(内存块里存的代码是可变的)
  • wrap 怎么写呢?根据外面的decorator函数的参数变着来:
    重点来了,开始改写bar:
  • 因为a='hello' not callable 所以有一行 print('hello') 的代码
  • 代码很少,接下来就 return了,return 的是被装饰函数的执行结果。
  • 为理解为wrap函数定义为这个时候去被装饰函数定义的内存块执行,并将被装饰函数的返回值返回出去。不知道这样说是否准确???
  • 相当于bar函数的函数体(内存中的块内容)变成了:
def bar(c):
    print(a)
    # 执行被装饰函数体
    print(c)
    # 将被装饰函数的返回值作为新函数的返回值,还是0
    return 0

调用被装饰后的函数显然应该为:

>>> bar('wold')
hello
world
0

第二种用法

@foo
def bar(c):
    print(c)
    return 0

装饰的作用是获得一个新函数

  • foo 函数是带参数的,所以把 bar作为参数执行 foo 函数 得到:
  • bar = foo(bar)
  • 仔细看foo的函数,如果参数是 callable 则返回 decorator 函数并且带上这个 foo 的参数,所以:
  • foo(bar) 变成了 decorator(bar) bar = decorator(bar)
  • 先执行 foo('hello') 得到 decorator
  • 于是 bar = decorator(bar)
  • decorator(bar) 执行得到的是一个 wrap 函数,说白了它的名字不重要,重要的是它里面的内容:
  • 里面的内容就这样来写 因为 a 是callable的,所以就不执行 print(a) 了,仅仅执行 func(*args),也就是将新函数的参数,被装饰函数返回它的返回值
  • 装饰器啥也没干,直接把被装饰器的代码拿去充数了。
  • 相当于bar函数的函数体(内存中的块内容)变成了:
def bar(c):
    # 执行被装饰函数
    print(c)
    # 将被装饰函数的返回值作为新函数的返回值,还是0
    return 0

调用被装饰后的函数应该为:

>>> bar('wold')
world
0

思考

定义一个函数其实是分配一个内存空间来装代码。
decorator() 函数执行的过程就是干这个事情:
创建一个 wrap 函数,最好把函数对象的引用丢出去。
这个函数干什么嗯
它先把print('hello') 这段代码记录下来。
再看decorator 的参数 func 是哪个,去他的代码块执行它,然后把返回值返回。

[参考]
https://www.jianshu.com/p/016573e8f63e

相关文章

  • TypeScript: 类的装饰器(三)

    带参数的类的装饰器 学习 python 的同学应该知道,python 中也有装饰器,而且 python 中的众多框...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • Python - 学习理解带参数的装饰器

    理解带参数的装饰器 参考文章 Python精进-装饰器与函数对象 加了装饰器这段代码从一个函数定义(不会执行任何东...

  • python装饰器

    装饰器简述 要理解装饰器需要知道Python高阶函数和python闭包,Python高阶函数可以接受函数作为参数,...

  • Python学习:带参数的装饰器

    问题 前面写了一个统计函数执行时间的装饰器,默认使用print函数打印执行日志。日志打印,不能假设一定会用prin...

  • 透析Python装饰器--透过现象看本质

    》眼花缭乱 Python的装饰器(也称语法糖)大致分为这几类: 无参数装饰器 有参数装饰器 装饰类的装饰器 无参数...

  • 透析Python装饰器-------------透过现象看本质

    》眼花缭乱 Python的装饰器(也称语法糖)大致分为这几类: 无参数装饰器 有参数装饰器 装饰类的装饰器 无参数...

  • 装饰器详解

    装饰器基本写法: 高级一点的装饰器 带参数的装饰器和类装饰器属于进阶的内容。在理解这些装饰器之前,最好对函数的闭包...

  • python 带参数的装饰器

    from functools import wrapsimport logging def logged(leve...

  • Python | 装饰器

    使用场景 装饰器 ' @ ' 使用 带参数装饰器 装饰器类

网友评论

    本文标题:Python - 学习理解带参数的装饰器

    本文链接:https://www.haomeiwen.com/subject/oxblfhtx.html