关于double装饰器的使用

关于double装饰器的使用


class MyException(Exception):
   """自定义异常类"""
   pass

def log(func):
   def f():
       f.__name__ = "测试函数"
       print("开始调用{}".format(func.__name__))
       try:
           func()
       except MyException:
           print("我成功捕获到了异常!!!")
       print("结束调用{}".format(func.__name__))
   return f

@log
@log
def v_for():
   """自定义异常抛出函数"""
   for i in range(1,100):
       if i == 5:
           raise MyException
       print(i)


if __name__ == '__main__':
   v_for()

用f.__name__ = “测试函数”定义了函数名称,但是最终输出的时候

http://img1.sycdn.imooc.com//climg/5dcb7f3c09bb840103340311.jpg

第一个print没有取到“测试函数”,但结尾的print取到了。请问是什么原因,具体的参数传递是怎么样的?

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学,你好。

1、多层装饰器会先执行离着被装饰函数近的那个,在执行log(v_for)函数时,在该函数中定义了f()函数,但并没有调用语句,即没有执行,而是作为了返回值,因此f()函数中的语句作为参数传递到了外层的装饰器log()函数中

2、下一步是执行log()函数中的内容,返回值为f。外层没有装饰器,因此会执行f中的内容,输出"开始调用f",此时func()为之前返回的f函数,执行f函数中的内容,此时f的__name__进行了修改,输出"开始调用v_for",f函数中的func()为v_for函数,当i=5时,抛出异常,输出'我成功捕获到了异常!!!'和'结束调用v_for',执行return f,返回到f函数中输出结束调用测试函数。

3、建议同学使用两个不同名称的装饰器,可以更清楚的明白执行流程。

如果我的回答解决了您的疑惑,请采纳!祝学习愉快~~~~

  • luluoverflow 提问者 #1
    “多层装饰器会先执行离着被装饰函数近的那个” @log @log2 def v_for(): 相当于 log(log2(v_for)) 我这样理解对吗?
    2019-11-14 20:20:45
  • 好帮手乔木 回复 提问者 luluoverflow #2
    同学你好:同学的理解是正确的,学习愉快^_^。
    2019-11-15 09:47:01
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
1.Python零基础入门
  • 参与学习           人
  • 提交作业       2727    份
  • 解答问题       8160    个

想要进入Python Web、爬虫、人工智能等高薪领域,你需要掌握本阶段的Python基础知识,课程安排带你高效学习轻松入门,学完你也能听得懂Python工程师的行业梗。

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师