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

理解带参数的装饰器

参考文章 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • 本文为《爬着学Python》系列第四篇文章。从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新。 在Pytho...
    SyPy阅读 2,489评论 4 11
  • 部分细节自己改了点,也加了点自己例子,基本上属于转载。转载出处:https://my.oschina.net/le...
    洛克黄瓜阅读 1,966评论 0 3
  • 前言 Python的修饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pa...
    linheimx阅读 627评论 0 4
  • 每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,...
    chen_000阅读 1,360评论 0 3
  • Python里我们经常能见到@开头的句法,也就是人们常说的装饰器(decorator)。装饰器是Python非常重...
    A遇上方知友阅读 856评论 0 0