Python修饰器

前话:

python的修饰器可以说是python语言最有灵性的一个功能了,看到网上有各种乱乱的文章,所以想自己写得亲民一下,如有错误请指出。

正文:

@fnc & 被修饰函数无参数

首先看一组简单的代码:

#修饰器
def dec(fn):
    print("此处fn为函数",fn)
    return fn

@dec
#被修饰函数
def my_fn():
    return "函数返回值"

print(my_fn())
>>> 此处fn为函数 <function my_fn at 0x0000020D87993B70>
>>> 函数返回值

以上的代码的修饰过程相当于my_fn => dec(my_fn)

@fnc & 被修饰函数有参数

接下来为被修饰函数加参数:

def dec(fn):
    print("此处fn为函数",fn)
    return fn

@dec
def my_fn(a):
    return "函数返回值为"+str(a)

print(my_fn('参数'))
>>> 此处fn为函数 <function my_fn at 0x00000230F14C3B70>
>>> 函数返回值为参数

此处依然为my_fn => dec(my_fn)

[小插曲]@fnc() & 被修饰函数无/有参数

在修饰器和被修饰函数都带参数前,先准备一个小插曲:

def dec_out():
    print('运行了dec_out')
    def dec_in (b):
        print("运行了dec_in")
        return b
    return dec_in

@dec_out()
def my_fn(a):
    return "函数返回值为"+str(a)

print(my_fn('my_fn参数'))
>>> 运行了dec_out
>>> 运行了dec_in
>>> 函数返回值为my_fn参数

看到这么多函数不要晕哦,我来解释一下:

  1. 首先运行my_fn函数时先进入了修饰器
  2. 遇到了dec_out时发现修饰器位置是一个被执行的函数(带着括号),于是便执行了一下
  3. 修饰器就因为里面的return dec_in就等效成了@dec_out() => @dec_in
  4. 因此my_fn('my_fn参数')就等效成了dec_in(my_fn)('my_fn参数')

在这里休息一下,我来解答一下可能存在的疑惑:

Q:为什么上一个情况my_fn => dec(my_fn),这次是dec_in(my_fn)('my_fn参数')

A:注意细节哦,上一个是my_fn,这次是my_fn('my_fn参数')

[正餐]@fnc(*arg) & 被修饰函数无/有参数

到了正餐了,有了上一个的铺垫,这次的也可以理解了

def dec_out(a):
    print("dec_out收到了",a)
    def dec_in (b):
        print("dec_in收到了",b)
        return b
    return dec_in

@dec_out("修饰器参数")
def my_fn(a):
    return "函数返回值为"+str(a)

print(my_fn('my_fn参数'))
>>> dec_out收到了 修饰器参数
>>> dec_in收到了 <function my_fn at 0x0000022432253AE8>
>>> 函数返回值为my_fn参数

有没有预知到这次的结局呢?某种意义上很清楚明了了:

  • @dec_out("修饰器参数")在运行的因为return dec_in等效成了@dec_in,进而my_fn('my_fn参数')等效成了dec_in (my_fn)('my_fn参数')

这里我就不人肉DEBUG来给各位讲解了。

[加餐]多重@fnc(*arg) & 被修饰函数无/有参数

一下比较简单:

def dec_first(fn):
    print("dec_first运行了")
    return fn

def dec_second(fn):
    print("dec_second运行了")
    return fn

@dec_first
@dec_second
def my_fn():
    return "my_fn运行了"

print(my_fn())
>>> dec_second运行了
>>> dec_first运行了
>>> my_fn运行了

从以上可以看出修饰器的运行顺序是从临近被修饰函数开始的。但是不要认为解释器是直接从第二个修饰器开始解释的。

请看一下代码:

def dec_first_out(a):
    print("dec_first_out收到了",a)
    def dec_first_in(fn):
        print("dec_first_in运行了")
        return fn
    return dec_first_in

def dec_second(fn):
    print("dec_second运行了")
    return fn

@dec_first_out('第一个参数')
@dec_second
def my_fn():
    return "my_fn运行了"

print(my_fn())
>>> dec_first_out收到了 第一个参数
>>> dec_second运行了
>>> dec_first_in运行了
>>> my_fn运行了

由此可以看出,解释器看到了最上方的修饰器处于运行状态(有括号)于是运行,后再按上面咱们发现的行为运行。

[最后的晚餐]被修饰的修饰器

听起来复杂,实际还是这么回事:

def dec_dec(fn):
    print("dec_dec运行了")
    return fn
@dec_dec
def dec(fn):
    print("dec运行了")
    return fn

@dec
def my_fn():
    return "my_fn运行了"

print(my_fn())
>>> dec_dec运行了
>>> dec运行了
>>> my_fn运行了

看到这里应该已经清楚了吧,最有灵性的功能也是按部就班的执行的。

总结

总的来看,python的修饰器可以这么理解:

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

推荐阅读更多精彩内容

  • 前言 Python的修饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pa...
    linheimx阅读 632评论 0 4
  • 前言 对python的修饰器的理解一直停留在"使用修饰器把函数注册为事件的处理程序"的层次,也是一知半解;这样拖着...
    MrYun阅读 24,444评论 3 35
  • “耐根要结婚了” “是呀,也不小了,该结婚了。” “我怎么听说是因为要给老方冲喜呀” “老方呀,真是的,应该享福的...
    依云70后阅读 893评论 0 6
  • 文|希昕 参赛编号385 谨以此篇,送给2018年高考考生 如今,四月,春意正浓! 去年,四月,我,在三年五班奋浴...
    錷篐阅读 386评论 2 25
  • 一、积极主动 生活中是否经常听到,或者我们也有这样的消极情绪“我根本没时间做”、“他把我气疯了”、“要是某某更耐心...
    一只奋力翱翔的鸽子阅读 316评论 1 0