当前位置:首页>python>Python装饰器详解,看完终于理解它了!

Python装饰器详解,看完终于理解它了!

  • 2026-10-11 12:49:44
Python装饰器详解,看完终于理解它了!

装饰器是Python中最强大但也最难理解的概念之一。很多人被它绕晕了。今天用最直白的方式,让你彻底搞懂装饰器的原理和实战用法!

★ P1:装饰器的本质——函数即对象

理解装饰器之前,先要明白一个核心概念:Python中函数也是对象,可以像变量一样传递。这是一切的基础。

函数作为返回值:

def outer():          def inner():          print('inner执行了')          return inner# 返回函数对象,不是调用它          result = outer()# result现在就是inner函数          result()# 调用result,执行inner          # 输出:inner执行了

函数作为参数:

def add(a, b):          return a + b          def multiply(a, b):          return a * b          def apply_twice(func, x, y):          return func(func(x, y), func(x, y))          print(apply_twice(add, 1, 2))# (1+2)+(1+2) = 6          print(apply_twice(multiply, 2, 3)) # (2*3)*(2*3) = 36

★ P2:手写第一个装饰器——理解原理

装饰器本质上就是一个"包装"函数。它接收一个函数作为参数,返回一个新的函数,在不改变原函数的基础上添加新功能。

最简单的装饰器:

def my_decorator(func):          def wrapper(*args, **kwargs):          print('=== 调用前 ===')          result = func(*args, **kwargs)# 调用原函数          print('=== 调用后 ===')          return result          return wrapper          @my_decorator          def say_hello(name):          print(f'你好,{name}!')          say_hello('Rose')          # 输出:          # === 调用前 ===          # 你好,Rose!          # === 调用后 ===

★ P3:实战装饰器——计时器、登录验证、日志

装饰器最大的价值是"横切关注点分离":把分散在多个函数中的重复逻辑(计时、认证、日志)抽离出来,统一处理。

装饰器1:函数计时器

import time          from functools import wraps          def timer(func):          @wraps(func)# 保留原函数元数据          def wrapper(*args, **kwargs):          start = time.time()          result = func(*args, **kwargs)          elapsed = time.time() - start          print(f'{func.__name__} 执行耗时: {elapsed:.4f}秒')          return result          return wrapper          @timer          def slow_function():          time.sleep(1)          return '完成'          slow_function()# slow_function 执行耗时: 1.0004秒

装饰器2:登录验证

from functools import wraps          def login_required(func):          @wraps(func)          def wrapper(*args, **kwargs):          if not getattr(func, 'is_logged_in', False):          print('❌ 请先登录!')          return None          return func(*args, **kwargs)          # 模拟登录标记          wrapper.is_logged_in = True          return wrapper          @login_required          def get_profile():          print('✅ 获取用户资料...')          get_profile()# ✅ 获取用户资料...

装饰器3:日志记录器

import logging          logging.basicConfig(level=logging.INFO)          logger = logging.getLogger(__name__)          def log_calls(func):          @wraps(func)          def wrapper(*args, **kwargs):          logger.info(f'调用 {func.__name__},参数: {args}, {kwargs}')          try:          result = func(*args, **kwargs)          logger.info(f'{func.__name__} 返回: {result}')          return result          except Exception as e:          logger.error(f'{func.__name__} 异常: {e}')          raise          return wrapper

★ P4:装饰器传参——带参数的装饰器工厂

如果装饰器本身需要参数,需要再包一层函数来接收参数,这叫"装饰器工厂"。

带参数的装饰器:

def repeat(times):# 接收装饰器参数          def decorator(func):# 接收被装饰函数          @wraps(func)          def wrapper(*args, **kwargs):          for _ in range(times):          result = func(*args, **kwargs)          return result          return wrapper          return decorator          @repeat(times=3)          def say_hi():          print('Hi!')          say_hi()# 输出3次'Hi!'

@wraps的作用:保留原函数的__name__、__doc__等元数据,不用@wraps的话,装饰后函数名会变成wrapper。

★ P5:总结

今天彻底讲透了Python装饰器,从原理到实战一网打尽。核心要点:          1. 函数即对象:函数可以赋值给变量、作为参数、作为返回值,这是装饰器的基础;2. 装饰器本质:一个返回函数的函数,接收原函数作为参数,在不修改原函数的情况下添加新功能;3. @wraps必须用:保留被装饰函数的元数据(名字、文档字符串),避免调试困扰 4. args/kwargs:wrapper函数用*args/**kwargs接收任意参数转发给原函数;5. 装饰器工厂:如果装饰器需要参数,再包一层函数返回装饰器;6. 实战场景:计时器(性能分析)、登录验证(权限控制)、日志(行为追踪)、重试机制(容错处理)。实践建议:不要为了用装饰器而用装饰器。当你在多个函数中写重复的前后置逻辑(如检查参数、记录日志、测量时间)时,就是抽取成装饰器的最佳时机。装饰器是代码重复的克星,用好了事半功倍!

☆☆☆ End ☆☆☆转角  ·  遇见  ·  程序猿
-------------------------
那是一抹淡淡的微光

它是数字世界里的一把杀猪刀

却总能巧夺天工

它的世界是纯粹0、1组合

却总能创造无尽幻想

......

本公众号关注数据价值分析、编程学习,将不定期更新社会热点数据分析结果、编程技巧,分享数据分析工具、方法、学习等内容,欢迎有兴趣的小伙伴加入。

最新文章

随机文章