当前位置:首页>python>装饰器:Python 有,Java 和 C++ 有没有?

装饰器:Python 有,Java 和 C++ 有没有?

  • 2026-09-02 19:06:13
装饰器:Python 有,Java 和 C++ 有没有?

一、什么是装饰

想象你买了一块普通的面包。

  • 直接吃:味道一般。
  • 在面包上涂一层奶油 → 变成奶油面包。
  • 再撒上巧克力碎 → 变成巧克力奶油面包。

装饰器做的事情就是这样:

在不改变面包(原函数)本身的前提下,给它“涂上”额外的功能(奶油、巧克力等)。

Python 里的装饰器,就是让你能写出这样的代码:

@涂奶油@撒巧克力def 面包():    print("我是普通面包")

调用 面包() 的时候,实际执行的是 先涂奶油、再撒巧克力、最后再执行原本的面包。


二、Python 装饰器

概念:
装饰器是一个函数(也可以是一个类),它接收一个函数作为参数,然后返回一个新的函数。
新函数里会包含原函数的功能,再加上一些额外的“装饰”。

语法:

def my_decorator(func):    def wrapper():        print("在调用原函数之前做点啥")   # 前置装饰        func()                           # 调用原函数        print("在调用原函数之后做点啥")   # 后置装饰    return wrapper@my_decoratordef say_hello():    print("Hello!")say_hello()

运行输出:

ounter(lineounter(lineounter(line在调用原函数之前做点啥Hello!在调用原函数之后做点啥

你看,say_hello 本身只负责打印 "Hello!",但通过 @my_decorator,它自动拥有了“前后加点料”的能力。


三、趣味代码样例

1. 计时装饰器(给函数计时)

import timedef timer(func):    def wrapper():        start = time.time()        func()        end = time.time()        print(f"{func.__name__} 耗时 {end - start:.4f} 秒")    return wrapper@timerdef slow_job():    time.sleep(1)    print("任务完成")slow_job()# 输出:# 任务完成# slow_job 耗时 1.0003 秒

2. 重复执行装饰器(让一个函数自动执行 3 次)

def repeat(times):    def decorator(func):        def wrapper():            for i in range(times):                print(f"第 {i+1} 次执行")                func()        return wrapper    return decorator@repeat(3)def dance():    print("跳舞")dance()

这里用了“带参数的装饰器”,本质是在外面再套一层函数来接收参数。

3. 多个装饰器叠加

def wear_hat(func):    def wrapper():        print("👒 戴上帽子")        func()    return wrapperdef wear_glasses(func):    def wrapper():        print("👓 戴上眼镜")        func()    return wrapper@wear_hat@wear_glassesdef me():    print("😀 这才是我")me()# 输出:# 👒 戴上帽子# 👓 戴上眼镜# 😀 这才是我

注意:装饰的顺序是从下往上(离函数最近的先装饰),但执行时是从上往下。
理解成“先贴最里面的衣服,再穿外面的外套”。


四、Java 和 C++ —— 有“装饰器”吗?

Java

有类似的设计模式叫“装饰器模式”,但没有 Python 这种 @ 语法糖。

Java 装饰器模式示例(比如给咖啡加糖加牛奶):

interface Coffee { String getCost(); }class SimpleCoffee implements Coffee {    public String getCost() { return "5元"; }}class SugarDecorator implements Coffee {    private Coffee coffee;    public SugarDecorator(Coffee c) { this.coffee = c; }    public String getCost() { return coffee.getCost() + " + 糖 1元"; }}// 使用时:Coffee c = new SugarDecorator(new SimpleCoffee());c.getCost(); // "5元 + 糖 1元"

与 Python 异同:

  • 相同:都是不修改原对象,动态添加功能。
  • 不同:
    • Python 装饰器是运行时对函数/类的直接替换,写法极其简洁。
    • Java 需要手动创建包装类,代码更啰嗦,但类型更安全(编译时)。
    • Java 的注解(Annotation) 长得像装饰器(如 @Override),但注解只是元数据,不改变行为,需要配合反射或注解处理器才有效,和 Python 装饰器不是一回事。

C++

没有内置的装饰器语法。但可以通过函数包装、lambda、std::function、继承等模拟类似效果。

C++ 模拟装饰器示例(用 lambda 包装):

#include<iostream>#include<functional>auto timer = [](std::function<void()> func) {    return [func]() {        std::cout << "开始计时" << std::endl;        func();        std::cout << "结束计时" << std::endl;    };};intmain(){    auto sayHi = []() { std::cout << "Hi!" << std::endl; };    auto decorated = timer(sayHi);    decorated();}

与 Python 异同:

  • 相同:都可以实现“用额外功能包装原函数”。
  • 不同:
    • Python 有 @ 语法糖,写起来像声明式;C++ 必须显式调用包装函数,代码可读性较差。
    • C++ 模板元编程可以实现编译期的“装饰”,但极其复杂,日常开发很少这样用。
    • C++ 更推荐使用继承 + 组合来替代装饰器需求。

五、总结:Python 装饰器的魅力

语言
是否有装饰器语法
实现方式
简洁度
Python
内置 @ 语法
函数接收函数,返回新函数
★★★★★
Java
无语法糖
手动编写装饰器模式类
★★☆
C++
无语法糖
用 lambda / std::function 手动包装
★★☆

Python 装饰器的优势:

  1. 极简:一行 @xxx 就能为函数增加缓存、日志、权限校验、计时等通用功能。
  2. 动态:可以在运行时替换或撤销装饰。
  3. 符合 Python 哲学:优雅、明确、简单。

初学小贴士:

  • 装饰器里的 wrapper 函数记得要 return 出来。
  • 如果原函数有参数,wrapper 要写成 *args, **kwargs 通用形式。
  • 想保留原函数的元信息(如名字、文档),可以用 functools.wraps(func)。

最新文章

随机文章