也谈python装饰器为什么需要两层嵌套?

文章包括以下内容:

1,装饰器的语法结构和运行顺序是怎样的?

2,为什么需要两层装饰器?单层的装饰器为什么会报错?  'NoneType' object is not callable .经修改不报错的单层装饰器为什么也不推荐使用?

3,python语言的设计者为啥要把他设计为双层?

最近在学习装饰器,过程中遇到许多困难,现在大体解决了,现在将一些经验分享给大家.由于是初学,可能存在错误,烦请指出讨论.

1,装饰器的语法结构和运行顺序

def log(func):                                         #1
    def wrapper(*args, **kw):                          #2
        print('call %s():' % func.__name__)            #3
        return func(*args, **kw)                       #4
    return wrapper                                     #5
@log                                                   #6
def now():                                             #7
print('2015-3-25')                                     #8

上面是一个简单的装饰器,它分为两层,

外层#1 定义装饰器的名称,参数为被装饰的函数a,#5 return装饰后的函数,即内层函数b;

内层b#2引入函数a的参数,并进行修饰,#4 return被装饰的函数a(),(注意是带有括号的)

这是装饰器标准的语法结构

下面谈谈装饰器的运行顺序

规则1,当程序读到#6 @log 时,上面的装饰器外层就会被执行,此时如果外层有print,将会被直接打印出来,

规则2,#7#8读取被装饰的函数a

规则3,#5,return被装饰之后的函数b,此时a已经指向了b,此后再调用a,就会调用b

至此上面的代码运行完毕,之后如果调用a

now()

就会直接运行被装饰的函数b

2,为什么需要两层装饰器?

如果直接一个单层的装饰器

def log(func):                                         #1
    print('call %s():' % func.__name__)                #2
    return func()                                      #3 
@log                                                   #4
def now():                                             #5
    print('2015-3-25')  

此时#4运行时就会运行#2的print,并且装饰器要求#3  return一个函数,而不是函数的值(正确写法是
return func

),因此#3的语法错误,会报错'NoneType' object is not callable

3如果改正为不要括号的写法

def log(func):                                         #1
    print('call %s():' % func.__name__)                #2
    return func                                        #3 
,则不会报错,但是会在@log时直接执行装饰器的内容(规则1),即执行print,此时装饰器返回的还是原函数a(规则3),所以之后调用函数a就无法触发装饰器

3,python的设计者为什么这么设计?

为什么不把单层的装饰器的执行顺序等价为现在的双层装饰器的执行顺序

一是两层结构可以传递被装饰的函数a的参数

二是不改变函数a和函数log原来的结构,因为log本身就是一个函数,他与其他函数有相同的执行顺序

@log

def now():

    pass

完全等价于now=log(now)


先这样,待补充

参考资料:

1,装饰器 - 廖雪峰的官方网站

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318435599930270c0381a3b44db991cd6d858064ac0000#0

2,python装饰器为什么要双层嵌套函数 - SegmentFault 思否

https://segmentfault.com/q/1010000006990592

3,python装饰器为什么要双层嵌套? - CSDN博客
https://blog.csdn.net/u010770184/article/details/53099089

4,[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考 - 推酷
https://www.tuicool.com/articles/FBZvya   这篇文章有错误,如果使用单层的装饰器,后面调用函数a(不加括号),函数并不会执行任何操作,当然也不会报错







  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值