前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >装饰器微妙之谈

装饰器微妙之谈

作者头像
Python知识大全
发布2022-02-23 14:58:48
2410
发布2022-02-23 14:58:48
举报
文章被收录于专栏:Python 知识大全Python 知识大全

简单的装饰器

代码语言:javascript
复制
def my_decorate(fun):
    def wrapper():
        print('这是个装饰器!')
        func()
     reture wapper
     
def greet():
 print('hello world')
greet = my_decorator(greet)
greet()
# 输出
这是个装饰器!
hello world

这段代码中变量 greet 指向了内部函数 wrapper(),而内部函数 wrapper() 中又会调用原函数 greet(),因此,最后调用 greet() 时,就会先打印 'wrapper of decorator',然后输出'hello world'。大家应该都明白!

这里的函数 my_decorator() 就是一个装饰器,它把真正需 要执行的函数 greet() 包裹在其中,并且改变了它的行为, 但是原函数 greet() 不变。

我们换一种写法,使用Python来装饰它

代码语言:javascript
复制
def my_decorator(func):   
    def wrapper():    
       print('wrapper of decorator')   
        func()  
    return wrapper
@my_decorator
def greet(): 
   print('hello world')
greet()

这里的@,我们称之为语法糖,@my_decorator就相当于 前面的greet=my_decorator(greet)语句,只不过更加 简洁。因此,如果你的程序中有其它函数需要做类似的装饰,你只需在它们的上方加上@decorator就可以了,这样 就大大提高了函数的重复利用和程序的可读性。

带有参数的装饰器

如果原函数 greet() 中,有参数需要传递给 装饰器怎么办?一个简单的办法,是可以在对应的装饰器函数 wrapper() 上,加上相应的参数,比如:

代码语言:javascript
复制
def my_decorator(func):
    def wrapper(message):
       print('wrapper of decorator')
       func(message)
     return wrapper
@my_decorator
def greet(message):
     print(message)
greet('hello world')
# 输出
wrapper of decorator
hello world

事实上,通常情况下,我们会把*args和**kwargs,作为 装饰器内部函数 wrapper() 的参数。

代码语言:javascript
复制
def my_decorator(func):
    def wrapper(*args, **kwargs):
       print('wrapper of decorator')
       func(*args, **kwargs)
    return wrapper

类装饰器

实际上,类也可 以作为装饰器。类装饰器主要依赖于函数__call_(),每当你调用一个类的示例时,函数__call__() 就会被执行一 次。

代码语言:javascript
复制
class Count:
   def __init__(self, func):
       self.func = func
       self.num_calls = 0
   def __call__(self, *args, **kwargs):
       self.num_calls += 1
       print('num of calls is: {}'.format(self.num_calls))
       return self.func(*args, **kwargs)
@Count
def example():
   print("hello world")
   
example()
# 输出
num of calls is: 1
hello world

example()
# 输出
num of calls is: 2
hello world

这里,定义了类 Count,初始化时传入原函数 func(), 而__call__() 函数表示让变量 num_calls 自增 1,然后打印,并且调用原函数。因此,在我们第一次调用函数 example() 时,num_calls 的值是 1,而在第二次调用时, 它的值变成了 2。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-02-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python 知识大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档