heidern0612 发表于 2018-12-25 16:29:40

Wrapper的语法糖---"@"函数修饰符和装饰器

本帖最后由 heidern0612 于 2018-12-25 17:54 编辑

写心得的过程都是自我思考的过程,借鉴了很多论坛前辈和互联网大佬的经验,仓促间难免有错,恳请指出,不胜感激。



Marry Christmas!!!


文章部分转载自伯乐在线帖子,原贴地址:戳我前进


首先引入装饰器相关:

1、@修饰符的定义:

‘@’修饰符必须出现在函数定义前一行,不允许和函数定义在同一行。

也就是说以下代码是非法的:@A    def f():

只可以在模块或类定义层内对函数进行修饰,不允许修饰一个类。

@修饰符更像是装饰器的一个浓缩,一个语法糖,那么,什么是装饰器呢?




2、装饰器作用:

Python的修饰器的英文名叫Decorator。

装饰器的作用是什么呢? 简单的理解就是:装饰原有的函数。(可以想象成普通的松树,圣诞节时装饰上各种美丽的彩灯和彩带。)

比如有一个函数func(a, b),它的功能是求a,b的差值。

我现在有一个需求,就是想对函数功能再装饰下,求完差值后再取绝对值,但是不能在func函数内部实现,这时候就需要装饰器函数了。

比如func = decorate(func)函数,将func函数作为参数传递给decorate函数,由decorate来丰富func函数,丰富完成后再返回给func,此时func的功能就丰富了。

以上有木有感觉很熟悉,函数调用自身,修饰完毕后再返回自身,像不像闭包?



Python的函数修饰符,“@”,与其说是修饰函数倒不如说是引用、调用它修饰的函数。

举个栗子:

def test(f):
    print "before ..."
    f()
    print "after ..."

@test
def func():
    print "func was called"


直接运行,输出结果:

before ...
func was called
after ...

上面代码可以看出来,只定义了两个函数: test和func,没有调用它们,如果没有“@test”,运行应该是没有任何输出的。


但是,Python解释器读到函数修饰符“@”的时候,后面步骤会是这样了:

1. 去调用 test函数,test函数的入口参数就是那个叫“func”的函数;

2. test函数被执行,入口参数的(也就是func函数)会被调用(执行);

换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。



以上需要注意的是:

1. 函数必须先定义,才能修饰它,反之的话会编译器不认识;

2. 修饰符“@”后面必须是之前定义的某一个函数;

3. 每个函数只能有一个修饰符,大于等于两个则不可以。






最后再看一个有趣的栗子,有关多个@执行顺序的问题:


def test3(func3):
    func3()
    print ("执行顺序3")

def test4(func4):
    func4()
    print ("执行顺序4")


def main():
    @test4
    def func1():
      print ("执行顺序1")
      @test3
      def func2():
            print( "执行顺序2")
main()


输出结果:

执行顺序1
执行顺序2
执行顺序3
执行顺序4



不看后面答案小朋友们能想出来为啥输出结果会是这样的吗?

难道结果不应该是4132吗?1234是什么鬼?

咳咳……



实例解析如下:

①、main函数执行,内部两部分:@test4 和def func1()。

②、@test4包裹在 def func1()外面,调用test4的函数test4(fun4),这里fun4是形参,而实际上func1()是个实参。

③、实参传入进去,首先打印出来的就是“执行顺序①”。 func1()内部也分两部分,一部分是@test3,def func2()。

④、同②道理,test3(func3),这里func3是形参,而实际传入的是fun2()实参。fun2()传入直接打印“执行顺序②”,调用完毕后执行test3里的print,打印“执行顺序③”

⑤、一步步返回上一级,返回到①里,test4里面最后打印“执行顺序④”



结合下面这一张蠢蠢的手绘图(字丑人更丑{:10_266:} )看上面步骤,应该能好理解不少:











qq664752 发表于 2019-1-17 19:17:27

66666666666,简单易懂

Twilight6 发表于 2020-4-10 14:43:40

顶下哈哈

雪影里 发表于 2020-5-5 10:34:42

感谢楼主

xianhe0621 发表于 2020-7-12 10:55:12

{:10_281:}

别虐我呀呀 发表于 2020-8-13 23:26:21

有点明白了,感谢感谢

刻舟求见 发表于 2020-8-20 22:36:46

终于看懂了,谢谢大佬

杨文龙 发表于 2020-9-11 10:38:30

通俗易懂,赞{:10_287:}
页: [1]
查看完整版本: Wrapper的语法糖---"@"函数修饰符和装饰器