跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Python算法

Python 装饰器核心原理解析

Python 装饰器是一种接受函数作为参数并返回新函数的函数,用于在不修改原代码前提下扩展功能。涵盖函数与类装饰器,以及@property、@classmethod 等内置用法。典型场景包括自动日志记录、性能计时及权限校验,通过闭包和包装函数实现逻辑解耦与复用。

Eee_123发布于 2026/1/23更新于 2026/7/2532 浏览

Python 装饰器核心原理解析

装饰器本质上是一个接受函数作为参数并返回一个新函数的函数。它允许我们在不修改原函数代码的情况下,为函数添加额外的功能。

简单来说,装饰器就像给礼物盒包装纸。杯子(原函数)的功能是盛水,但为了美观或保护,我们给它套上一个盒子(装饰器)。盒子本身不改变杯子的用途,但赋予了它新的属性。

一、基本概念

下面通过一个例子来解释这个概念。

假设现在有一个普通函数:

def say_hello():
    print("你好!")

say_hello()
# 输出:你好!

假如我们想在说'你好'之前和之后都加上一些辅助语句,传统做法是修改原函数。但使用装饰器,我们可以这样做:

def decorator(func):
    # 这是具体的装饰逻辑
    def wrapper():
        print("准备开始啦!")
        func()  # 这里调用原来的函数
        print("结束啦!")
    return wrapper

def say_hello():
    print("你好!")

# 把 say_hello 这个函数,放进 decorator 这个包装盒里
decorated_say_hello = decorator(say_hello)
# 运行包装后的新函数
decorated_say_hello()
# 输出结果:
# 准备开始啦!
# 你好!
# 结束啦!

通过上面的例子便能理解那句话:'装饰器本质上是一个接受函数作为参数并返回一个新函数的函数。'在 decorator 函数中,参数是另一个函数(func),并且最终返回了一个函数(wrapper)。

很多人对这种嵌套形式可能不太理解。可以这样想:decorator 是装饰器本身,wrapper 是包装层。就像用包装纸包裹苹果,不管材质如何,包裹后就可以说对这个苹果进行了装饰。

更简洁的写法:@ 语法

Python 提供了更简单的语法糖,直接用 @装饰器名字:

def decorator(func):
    def wrapper():
        print("准备开始啦!")
        func()
        print("结束啦!")
    return wrapper

@decorator  # 就像给函数戴上一顶魔法帽子
def say_hello():
    print("你好!")

say_hello()
# 直接调用就会自动被装饰
# 输出结果:
# 准备开始啦!
# 你好!
# 结束啦!

二、装饰器的类型

1. 函数装饰器

不带参数的函数装饰器
# 这是一个'加工机器',它会给任何函数加上'说你好'的功能
def say_hello_machine(func):
    def wrapper():
        print("你好!")  # 加上的'巧克力酱'
        func()           # 原来的圆筒冰淇淋
        print("再见!")  # 加上的'坚果碎'
    return wrapper

@say_hello_machine  # 直接把'圆筒'放进'机器'
def my_name():
    print("我是小明")

my_name()
# 输出结果:
# 你好!
# 我是小明
# 再见!
带参数的函数装饰器

有时候我们需要动态配置装饰器的行为,比如决定说多少次'你好'。

# 这个机器自己需要一个参数,来决定说多少次你好
def say_hello_machine_times(times):
    # 机器的调节按钮
    def real_decorator(func):
        def wrapper():
            for i in range(times):
                print("你好!")
            func()
        return wrapper
    return real_decorator

# 使用这个高级机器,把'调节按钮'拧到 3
@say_hello_machine_times(3)
def my_name():
    print("我是小明")

my_name()
# 输出结果:
# 你好!
# 你好!
# 你好!
# 我是小明

2. 类装饰器

除了用函数做'加工机器',我们还可以用一个'类'来组装成一个机器。

class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self):
        print("类装饰器说:开始!")
        self.func()
        print("类装饰器说:结束!")

@MyDecorator
def my_name():
    print("我是小明")

my_name()
# 输出结果:
# 类装饰器说:开始!
# 我是小明
# 类装饰器说:结束!

3. 内置装饰器

Python 标准库提供了一些常用的内置装饰器。

(1) @property

它能把一个方法变成属性,调用时无需括号。

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def area(self):
        return self.radius * self.radius * 3.14

circle = Circle(10)
print(circle.area)  # 直接当属性用,不用加括号!
# 输出:314.0
(2) @classmethod

规定这个方法属于整个类,而不是某个具体对象。

class ThirdGradeClass:
    total_students = 0

    def __init__(self, name):
        self.name = name
        ThirdGradeClass.total_students += 1

    @classmethod
    def get_total_students(cls):
        return cls.total_students

xiaoming = ThirdGradeClass("小明")
xiaohong = ThirdGradeClass("小红")

# 调用类方法,不需要通过某个具体的学生,通过类名就可以调用
print(ThirdGradeClass.get_total_students())
# 输出:2
(3) @staticmethod

把一个普通的函数'挂'在类里面,但与类和对象都没有关系,只是一个工具。

class ThirdGradeClass:
    @staticmethod
    def add_numbers(a, b):
        return a + b

result1 = ThirdGradeClass.add_numbers(5, 3)
result2 = xiaoming.add_numbers(10, 2)

print(result1)  # 输出:8
print(result2)  # 输出:12

三、装饰器的应用场景

在实际开发中,装饰器常用于解耦业务逻辑与横切关注点(如日志、权限、性能监控)。

场景 1:自动日志记录

你想知道哪些函数被执行了,并在控制台记录下来。如果没有装饰器,每个函数都要手动写 print。

没有装饰器:

def build_house():
    print("记录:玩家建造了房子!")
    print("砰!砰!砰!一栋房子盖好了!")

def mine_ore():
    print("记录:玩家挖矿了!")
    print("镐子咣咣咣,挖到了钻石!")

如果有一百个动作,就要写一百遍,维护成本极高。

使用装饰器:

def log_action(func):
    def wrapper():
        print(f"记录:玩家进行了 {func.__name__} 操作!")
        func()
    return wrapper

@log_action
def build_house():
    print("砰!砰!砰!一栋房子盖好了!")

@log_action
def mine_ore():
    print("镐子咣咣咣,挖到了钻石!")

build_house()
mine_ore()

效果: 代码变得非常干净。要修改记录格式,只需要改装饰器这一个地方。

场景 2:速度计时

测试一下某个动作耗时多久。

import time

def timer(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"【{func.__name__}】动作耗时:{end_time - start_time:.2f} 秒")
    return wrapper

@timer
def chop_tree():
    print("咔嚓...咔嚓...")
    time.sleep(2)
    print("获得木头*5!")

chop_tree()

效果: 不用在 chop_tree 里写任何计时代码,穿上 @timer 装备即可。

场景 3:权限检查

有些操作需要满足特定条件(如等级)才能执行。

player_level = 8

def check_level(required_level):
    def decorator(func):
        def wrapper():
            if player_level >= required_level:
                func()
            else:
                print(f"权限不足!需要 {required_level} 级,你只有 {player_level} 级。")
        return wrapper
    return decorator

@check_level(required_level=10)
def use_ender_chest():
    print("成功打开末影箱,存取物品!")

use_ender_chest()

效果: 权限检查逻辑集中在装饰器内,所有需要检查的函数只需'穿'上装备,无需重复编写 if ... else ...。

目录

  1. Python 装饰器核心原理解析
  2. 一、基本概念
  3. 输出:你好!
  4. 把 say_hello 这个函数,放进 decorator 这个包装盒里
  5. 运行包装后的新函数
  6. 输出结果:
  7. 准备开始啦!
  8. 你好!
  9. 结束啦!
  10. 更简洁的写法:@ 语法
  11. 直接调用就会自动被装饰
  12. 输出结果:
  13. 准备开始啦!
  14. 你好!
  15. 结束啦!
  16. 二、装饰器的类型
  17. 1. 函数装饰器
  18. 不带参数的函数装饰器
  19. 这是一个“加工机器”,它会给任何函数加上“说你好”的功能
  20. 输出结果:
  21. 你好!
  22. 我是小明
  23. 再见!
  24. 带参数的函数装饰器
  25. 这个机器自己需要一个参数,来决定说多少次你好
  26. 使用这个高级机器,把“调节按钮”拧到 3
  27. 输出结果:
  28. 你好!
  29. 你好!
  30. 你好!
  31. 我是小明
  32. 2. 类装饰器
  33. 输出结果:
  34. 类装饰器说:开始!
  35. 我是小明
  36. 类装饰器说:结束!
  37. 3. 内置装饰器
  38. (1) @property
  39. 输出:314.0
  40. (2) @classmethod
  41. 调用类方法,不需要通过某个具体的学生,通过类名就可以调用
  42. 输出:2
  43. (3) @staticmethod
  44. 三、装饰器的应用场景
  45. 场景 1:自动日志记录
  46. 场景 2:速度计时
  47. 场景 3:权限检查
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 LangChain 实现数据库问答机器人
  • OpenClaw 开源智能 AI 助理云端部署方案
  • AI 内容安全审核:Qwen3Guard-Gen-WEB 部署与使用教程
  • AI 编程实战:自动化代码生成、低代码与算法优化
  • 4 款实用 AI 技能工具已在 GitHub 开源
  • FPGA Aurora 64B/66B 协议开发与配置实战
  • CentOS 7 安装 MySQL 8.0.45 解决 GPG 密钥不匹配问题
  • SunPositionCalc:基于 C++ 的太阳位置精确计算实战解析
  • Java 全栈工程师面试实录:从基础到复杂场景
  • Spring Cloud Gateway Web MVC 使用指南
  • 大模型训练全流程解析:从自监督学习到反向传播
  • 免费开源 AI 工具 CoPaw 与 OpenFang 本地部署指南
  • 2024 年人工智能 PC 行业趋势与消费者洞察白皮书
  • C++ 异常处理机制:异常捕获、自定义异常与实战应用
  • Java8 ConcurrentHashMap 底层数据结构与核心方法流程
  • 网络安全技术核心学习内容及就业前景分析
  • 数据结构:KMP 算法、Trie 树与并查集详解
  • SQL 实战:筛选员工当前有效薪水记录
  • 渐进式 AIGC 系统:Nano-Banana 2 绘画与 VEO/Sora 视频生成私有化部署
  • 宇树机器人 G1 二次开发:导航仿真与地图转换教程

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online