Python语法:装饰器(decorator)

一、定义

装饰器 decorator 或者称为包装器,是对函数的一种包装。

二、作用

  1. 它能使函数的功能得到扩充,而同时不用修改函数本身的代码。
  2. 它能够增加函数执行前、执行后的行为,而不需对调用函数的代码做任何改变。

三、举例

初始化函数


   
   
  1. # 函数hello,输出 hello + name 的字符串
  2. def hello( name):
  3. return 'hello ' + name

希望实现功能:在每一个调用 hello 函数的时候,将输出的字符串用 <tag>包住

例如:hello john 变成 <tag>hello john<tag>
   
   

方法一:自定义wrapper函数

这种方法成功修改了函数 hello 的行为,不过需要修改对 hello的调用。

每一个调用hello 的地方,都要给成调用wrapper,并修改参数列表


   
   
  1. def hello( name):
  2. return 'hello ' + name
  3. def wrapper( tag, func, *arg, **kvargs):
  4. tag = "<" + tag + ">"
  5. return tag + func(*arg, **kvargs) + tag
  6. if __name__ == "__main__":
  7. print(wrapper( 'p', hello, 'john'))

输出

方法二:自定义decorator函数

为了不改变对 hello的调用。我们需要得到一个新的函数对象,它修改 hello的行为,并用这个对象对 hello赋值。

从而调用 hello的时候,调用的是扩充行为后的 hello


   
   
  1. def hello( name):
  2. return 'hello ' + name
  3. def myDecorator( func, tag):
  4. def myWrapper( *arg, **kvargs): # 重新包装func,其参数列表与func一致
  5. sign = "<" + tag + ">"
  6. return sign + func(*arg, **kvargs) + sign
  7. return myWrapper
  8. hello = myDecorator(hello, "div") # 用新的函数对象修改hello
  9. if __name__ == "__main__":
  10. print(hello( "john"))

 这样,只要hello被myDecorator 赋值一次,以后再调用hello 时,就调用的是包装后的函数

输出

方法三:python的decorator

python 的装饰器所做的事与方式2类似

它通过语法糖使装饰器看起来更清晰、简介,而不用每次都书写方式2中第7行代码 hello = myDecorator(hello, "div")


   
   
  1. def setTag( tag): # 由于此装饰器需要参数,所以要再套一层
  2. def myDecorator( func): # 装饰器的核心,接受函数对象做参数,返回包装后的函数对象
  3. def myWrapper( *arg, **kvargs): # 包装的具体过程
  4. sign = "<" + tag + ">"
  5. return sign + func(*arg, **kvargs) + sign
  6. return myWrapper
  7. return myDecorator
  8. @setTag("div") # 用@标签在定义函数时套上装饰器
  9. def hello( name):
  10. return 'hello' + name
  11. if __name__ == '__main__':
  12. print(hello( 'john'))

本质上,方式2 与 方式3 完成的是同一件事,只不过方式3 比方式2 代码更简洁,方便。

比如,现在要给 hello 函数套上三个标签<body><div><p>

如果用方式2

hello = myDecorator(myDecorator(myDecorator(hello, "body"),"div"),"p")
   
   

如果用方式3


   
   
  1. @myDecorator("body")
  2. @myDecorator("div")
  3. @myDecorator("p")
  4. def hello( name)
  5. return 'hello' + name

在多个装饰器嵌套的情况下,python内置的decorator 结构更清晰。

伪代码:


   
   
  1. def myDecorator( ...):     #定义装饰器,可能带参数
  2. def decorator( func): #装饰器核心,以被装饰的函数对象为参数,返回装饰后的函数对象
  3. def wrapper( *args, **kvargs): #装饰的过程,参数列表适应不同参数的函数
  4. ... #修改函数调用前的行为
  5. func(*args, **kvargs) #调用函数
  6. ... #修改函数调用后的行为
  7. return wrapper
  8. return decorator
  9. @myDecorator(...):     #给函数加上装饰器
  10. def myFunc( ...):     #自己定义的功能函数
  11. ...

知识点:

  1. 在python中,当*和**符号出现在函数定义的参数中时,表示任意数目参数收集。*arg表示任意多个无名参数,类型为tuple;**kwargs表示关键字参数,为dict,使用时需将*arg放在**kwargs之前,否则会有“SyntaxError: non-keyword arg after keyword arg”的语法错误
  2. 在函数调用时,*会以单个元素的形式解包一个元祖,使其成为独立的参数。
  3. 在函数调用时,**会以键/值对的形式解包一个字典,使其成为独立的关键字参数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值