装饰器微妙之谈

简介: 装饰器微妙之谈


简单的装饰器


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来装饰它

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() 上,加上相应的参数,比如:


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() 的参数。


def my_decorator(func):
    def wrapper(*args, **kwargs):
       print('wrapper of decorator')
       func(*args, **kwargs)
    return wrapper

类装饰器


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

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。

相关文章
|
编译器 C语言 C++
C++——函数
C++——函数
171 0
C++——函数
|
11天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1244 5
|
10天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1230 87
|
11天前
|
云栖大会
阿里云云栖大会2025年9月24日开启,免费申请大会门票,速度领取~
2025云栖大会将于9月24-26日举行,官网免费预约畅享票,审核后短信通知,持证件入场
1804 13
|
20天前
|
人工智能 运维 安全
|
4天前
|
资源调度
除了nrm-pm,还有哪些工具可以管理多个包管理器的源?
除了nrm-pm,还有哪些工具可以管理多个包管理器的源?
236 127