继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

浅谈装饰器

忽然笑
关注TA
已关注
手记 304
粉丝 64
获赞 276

 1 def foo(func): 2     def inner(*args, **kwargs): 3         print("主函数运行之前") 4         r = func(*args, **kwargs) 5         # return r, "主函数返回值" 6  7     return inner 8  9 10 def test(*args, **kwargs):11     return max(args)12 13 14 test = foo(test)15 16 print(test(2, 3, 4, ))

复制代码

上面的代码等价于下面的代码:

复制代码


def foo(func):
    def inner(*args, **kwargs):
        print("主函数运行之前")
        r = func(*args, **kwargs)
        # return r, "主函数返回值"

    return inner


@foo
def test(*args, **kwargs):
    return max(args)


# test = foo(test)

print(test(2, 3, 4, ))

复制代码

两者的运行结果也都是一样的:

 

主函数运行之前
None

 

也许你会很奇怪,为什么用print(test(2, 3, 4, ))会返回None,我当时也是一头雾水,下面我就解释一下这是为什么,这还是跑不了装饰器原理,一定要理解其原理。

以上面的两段代码为例,@foo替代了test = foo(test)

test = foo(test)的意思就是把函数test当做参数穿入函数foo中,那么foo的形参func(形参就相当于变量)就指向了函数test(也就是指向了test函数的内存地址),然后foo函数最下面的return返回inner

这些都是在执行“test = foo(test)”等号后面的,接下来执行等号赋值,把foo(test)结果也就是inner(内函数)赋值给等号左边的test,注意,此时等号左右两端的test完全不同,分别指向两个函数,
这也就是为什么我们print(test(2, 3, 4 ))后,打印None,实际上我们是执行了print(inner(2, 3, 4)),其并无返回值。那我们怎么打印出主函数也就是def test(*args, **kwargs):的返回值呢?看下面的代码:
   

 

复制代码

 1 def foo(func): 2     def inner(*args, **kwargs): 3         print("主函数运行之前") 4         r = func(*args, **kwargs) 5         return r, "主函数返回值" 6  7     return inner 8  9 10 @foo11 def test(*args, **kwargs):12     return max(args)13 14 15 # test = foo(test)16 17 print(test(2, 3, 4, ))

复制代码

 

此段代码的结果为:

 

主函数运行之前
(4, '主函数返回值')

 

此时用变量r指向主函数的返回值,在return r 利用print(test(2, 3, 4, ))中的print()就打印出了主函数的返回值。其实这也就是装饰器的实现原理,既不改变原代码,调用方式也没有改变却实现了调用主函数并在装饰器

中增加了新的功能,比如验证权限等。还有一种装饰器叫做类装饰器,还请新人们多多求索,努力学习。

原文出处:https://www.cnblogs.com/tttzqf/p/9386104.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP