python装饰器解释

一开始感觉有点难理解,不知道为啥,但是看了这段代码就秒懂了。

这就是一个简单的装饰器的例子:说白了就是在装饰器里新建了一个新函数,新函数会调用老函数,但是会自己装饰一些内容。最后返回这个新函数替代老函数的返回。

python 复制代码
def decorator(old_func):
    def new_func():
        print("调用前")
        old_func()
        print("调用后")

    return new_func

含义是:

decorator(old_func):接收旧函数

new_func():定义一个新函数

old_func():在新函数里面调用旧函数

return new_func:把新函数返回出去,替换原来的函数名

所以之后:

python 复制代码
@decorator
def hello():
    print("hello")

等价于:

python 复制代码
def hello():
    print("hello")

hello = decorator(hello)

最后 hello() 实际执行的是 new_func():

调用前

hello

调用后

不过注意:不是所有装饰器都必须这么写。

有些装饰器只是做"注册",然后原样返回旧函数:

python 复制代码
def decorator(old_func):
    registry.append(old_func)
    return old_func

这种没有新函数包装,只是把函数登记一下。

有个很好的例子:(下面没有过多的装饰,只是把老函数注册到了一个字典)

python 复制代码
class A2AServer:
    def __init__(self):
        self.skills = {}  # 存放所有技能

    def skill(self, name):
        # 这一层接收技能名称(如 "multiply"),返回一个装饰器函数
        def decorator(func):
            # 这一层接收你写的函数,把它注册到 skills 字典里
            self.skills[name] = func
            print(f"✅ 技能 '{name}' 注册成功")
            return func  # 这里原样返回你的函数
        return decorator

# 现在你就能用上面那种写法了
calculator = A2AServer()

@calculator.skill("multiply")
def multiply_numbers(query):
    return "计算结果..."

# 检查是否注册成功
print(calculator.skills)  # {'multiply': <function multiply_numbers ...>}

Python 解释器看到 @,知道要执行:

python 复制代码
multiply_numbers = calculator.skill("multiply")(multiply_numbers)

第三步:calculator.skill("multiply")

调用 skill 方法,传入 "multiply":

python 复制代码
def skill(self, name):          # name = "multiply"
    def decorator(func):        # 还没执行,只是定义了内部函数
        self.skills[name] = func
        print(f"✅ 技能 '{name}' 注册成功")
        return func
    return decorator            # 返回 decorator 这个函数本身

calculator.skill("multiply") 的返回值是 decorator 这个函数。

此时代码等价于:

python 复制代码
multiply_numbers = decorator(multiply_numbers)

第四步:decorator(multiply_numbers)

把 multiply_numbers 这个函数作为参数,调用 decorator:

python 复制代码
def decorator(func):            # func = multiply_numbers 这个函数
    self.skills[name] = func    # self.skills["multiply"] = multiply_numbers
    print(f"✅ 技能 '{name}' 注册成功")  # 输出: ✅ 技能 'multiply' 注册成功
    return func                 # 返回 multiply_numbers 本身

decorator 做了两件事:

  1. 把 multiply_numbers 存进 calculator.skills["multiply"]

  2. 把 multiply_numbers 原样返回


第五步:multiply_numbers = decorator(multiply_numbers)

decorator 返回了 multiply_numbers 本身,又赋值给 multiply_numbers。

所以 multiply_numbers 还是原来的函数,没有变。 只是在这个过程中被"注册"到了 calculator.skills 字典里。

【定义阶段,代码加载时】

  1. calculator = A2AServer()

→ calculator.skills = {}

  1. @calculator.skill("multiply")

→ 调用 calculator.skill("multiply")

→ 返回 decorator 函数

→ 调用 decorator(multiply_numbers)

→ self.skills"multiply" = multiply_numbers

→ 输出: ✅ 技能 'multiply' 注册成功

→ 返回 multiply_numbers

→ multiply_numbers = multiply_numbers(不变)

  1. print(calculator.skills)

→ 输出: {'multiply': <function multiply_numbers at 0x...>}

相关推荐
wangchunyu11416 分钟前
JAVA JVM内存结构与运行时数据区
java·开发语言·jvm
slongzhang_19 分钟前
linux 递归删除源码文件|递归删除目录下 *.js,但排除 *.min.js
linux·开发语言·javascript
云和数据.ChenGuang2 小时前
Python 常见特殊方法详解:__new__、__init__、__del__、__str__、__repr__ 与 __getattribute__
开发语言·人工智能·python·1024程序员节
xyouyuweizhu2 小时前
字节流与字符流:Java IO 的两条主线该怎么选
java·开发语言·python
迪菲赫尔曼2 小时前
【基础篇 04】第一次使用终端:命令在哪里输入,电脑现在又“站”在哪里?
python·yolo·目标检测
qianbo_insist3 小时前
# 在 Qwen3.5-2B 上把 GDN-1 无损换成 GDN-2:一次完整的架构手术实验(负结果)
人工智能·pytorch·python·架构
多弗朗皮卡丘3 小时前
C++的IO流
开发语言·c++·io流·文件io流
骑着蜗牛撵大象3273 小时前
AI Agent 工程化开发实战(三):用 StateGraph 给智能体搭一条可回放的状态流水线
java·开发语言·jvm·ai·状态管理·langgraph·stategraph
itmigrate3 小时前
Rust 里的所有权误区:不是不写 clone 就叫高性能
开发语言·后端·rust
Brilliantwxx3 小时前
【Linux】 文件访问与路径解析:目录、文件名、dentry、路径缓冲与 dcache 全解析
linux·运维·服务器·开发语言·spring