page contents

深入浅出Python装饰器:提升代码优雅性与复用率的终极秘籍!

记得刚入行那会儿,我接手了一个老项目。里面到处都是重复的日志记录代码,每个函数开头都要写一遍记录执行时间的逻辑,简直让人头皮发麻。那时候我还不懂装饰器,只能一个个函数去复制粘贴,改来改去,简直是噩梦。后来遇到了装饰器,才发现原来Python有这么优雅的解决方案。就像给函数穿了一件外套,既保持了原有功能,又增加了新的能力。

attachments-2025-08-B5ZPnoqr68ae6157a46aa.jpg记得刚入行那会儿,我接手了一个老项目。里面到处都是重复的日志记录代码,每个函数开头都要写一遍记录执行时间的逻辑,简直让人头皮发麻。那时候我还不懂装饰器,只能一个个函数去复制粘贴,改来改去,简直是噩梦。后来遇到了装饰器,才发现原来Python有这么优雅的解决方案。就像给函数穿了一件外套,既保持了原有功能,又增加了新的能力。

01 装饰器的基础

装饰器,简单来说,就是一个函数包装器。你可以把它想象成一个魔法盒子,把你的函数放进去,出来的时候就有了额外的超能力,但本质功能没变。

def my_decorator(func):

def wrapper(*args, **kwargs):

        print(f"函数{func.__name__}开始执行了")

        result = func(*args, **kwargs)

        print(f"函数{func.__name__}执行完毕")

return result

return wrapper


@my_decorator

def say_hello(name):

    print(f"Hello, {name}!")

调用函数 say_hello("张三"),只要在函数上加个@my_decorator,就自动有了执行前后的日志记录功能。这比在每个函数里手动添加日志代码优雅多了。

02 实际应用中的装饰器

在实际项目中,我最常用装饰器来做以下几件事:性能监控装饰器 这个装饰器可以用来监控函数的执行时间。

import time

import functools


def timing_decorator(func):

    @functools.wraps(func)  # 保持原函数的元信息

def wrapper(*args, **kwargs):

        start_time = time.time()

        result = func(*args, **kwargs)

        end_time = time.time()

        print(f"{func.__name__}执行耗时:{end_time - start_time:.4f}秒")

return result

return wrapper


@timing_decorator

def slow_function():

    time.sleep(2)

return"处理完毕"

有一次线上接口响应特别慢,就是用这个装饰器快速定位到了性能瓶颈。权限验证装饰器 用装饰器进行权限验证,简化了代码逻辑。

def require_auth(role):

def decorator(func):

def wrapper(*args, **kwargs):

            user_role = get_current_user_role()  # 假设有这个函数

if user_role != role:

raise PermissionError(f"需要{role}权限")

return func(*args, **kwargs)

return wrapper

return decorator


@require_auth("admin")

def delete_user(user_id):

# 删除用户的逻辑

pass

03 装饰器的高级用法

装饰器的高级用法真的很强大,以下是一些常见场景:带参数的装饰器 这是我用得最多的装饰器类型。比如,重试机制:

def retry(max_attempts=3, delay=1):

def decorator(func):

        @functools.wraps(func)

def wrapper(*args, **kwargs):

for attempt in range(max_attempts):

try:

return func(*args, **kwargs)

except Exception as e:

if attempt == max_attempts - 1:

raise e

                    print(f"第{attempt + 1}次尝试失败,{delay}秒后重试")

                    time.sleep(delay)

return wrapper

return decorator


@retry(max_attempts=5, delay=2)

def unstable_api_call():

import random

if random.random() < 0.7:

raise Exception("网络错误")

return"成功获取数据"

这个重试装饰器在调用第三方API时简直是救命稻草。类装饰器 类装饰器也很有趣,虽然不常用,但在某些场景下非常适用。

classCountCalls:

def __init__(self, func):

        self.func = func

        self.count = 0


def __call__(self, *args, **kwargs):

        self.count += 1

        print(f"{self.func.__name__}被调用了{self.count}次")

return self.func(*args, **kwargs)


@CountCalls

def greet(name):

return f"你好{name}"

04 装饰器中的坑

装饰器虽然好用,但也有一些坑要注意:忘记使用 functools.wraps 如果你忘记使用 functools.wraps,会导致原函数的元信息丢失,这在调试时非常麻烦。错误示例

def bad_decorator(func):

def wrapper(*args, **kwargs):

return func(*args, **kwargs)

return wrapper

正确示例

def good_decorator(func):

    @functools.wraps(func)

def wrapper(*args, **kwargs):

return func(*args, **kwargs)

return wrapper

装饰器执行顺序 多个装饰器叠加时,执行顺序是从下往上的:

@decorator_a

@decorator_b

@decorator_c

def my_function():

pass

等同于my_function = decorator_a(decorator_b(decorator_c(my_function)))

这个顺序经常搞混,所以我现在会在代码中写注释来提醒自己。

05 总结

装饰器真的是Python中最优雅的特性之一。掌握了装饰器,代码的复用性和可维护性会有质的提升。特别是在处理横切关注点的时候,比如日志、缓存、权限验证这些,装饰器简直是完美的解决方案。建议大家多在项目中实践,从简单的功能开始,慢慢积累自己的装饰器库。记住,好的代码不仅要能跑,还要优雅易读。装饰器就是帮你写出优雅代码的利器!

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

2172 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2172 文章
  3. Pack 1335 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章