翼度科技»论坛 编程开发 python 查看内容

< Python全景系列-9 > Python 装饰器:优雅地增强你的函数和类

9

主题

9

帖子

27

积分

新手上路

Rank: 1

积分
27
欢迎来到我们的系列博客《Python全景系列》第九篇!在这个系列中,我们将带领你从Python的基础知识开始,一步步深入到高级话题,帮助你掌握这门强大而灵活的编程语法。无论你是编程新手,还是有一定基础的开发者,这个系列都将提供你需要的知识和技能。
** 装饰器在 Python 中扮演了重要的角色,这是一种精巧的语言特性,让我们能够修改或增强函数和类的行为,无需修改它们的源代码。这篇文章将深入探讨装饰器的所有相关主题,包括装饰器的基础知识、实现与使用、工作原理,以及通过实际例子学习装饰器的独特用法。**
Python 装饰器深入探讨

在 Python 中,装饰器提供了一种简洁的方式,用来修改或增强函数和类的行为。装饰器在语法上表现为一个前置于函数或类定义之前的特殊标记:
  1. @simple_decorator
  2. def hello_world():
  3.     print("Hello, world!")
复制代码
在这个例子中,simple_decorator 是一个装饰器,它作用于下方的 hello_world 函数。装饰器在概念上就像一个包装器,它可以在被装饰的函数执行前后插入任意的代码,进而改变被装饰函数的行为。
参数化装饰器

我们还可以进一步将装饰器参数化,这让装饰器的行为更具灵活性。比如,我们可以定义一个装饰器,让它在函数执行前后打印自定义的消息:
  1. def message_decorator(before_message, after_message):
  2.     def decorator(func):
  3.         def wrapper(*args, **kwargs):
  4.             print(before_message)
  5.             result = func(*args, **kwargs)
  6.             print(after_message)
  7.             return result
  8.         return wrapper
  9.     return decorator
  10. @message_decorator("Start", "End")
  11. def hello_world():
  12.     print("Hello, world!")
复制代码
在这个例子中,message_decorator 是一个参数化装饰器,它接受两个参数,分别代表函数执行前后要打印的消息。
理解装饰器的工作原理

在 Python 中,函数是第一类对象。这意味着函数和其他对象一样,可以作为变量进行赋值,可以作为参数传给其他函数,可以作为其他函数的返回值,甚至可以在一个函数里面定义另一个函数。这个特性是实现装饰器的基础。
  1. def decorator(func):
  2.     def wrapper():
  3.         print('Before function execution')
  4.         func()
  5.         print('After function execution')
  6.     return wrapper
  7. def hello_world():
  8.     print('Hello, world!')
  9. decorated_hello = decorator(hello_world)
  10. decorated_hello()
复制代码
在这个例子中,decorator 函数接收一个函数 hello_world 作为参数,并返回了一个新的函数 wrapped_func。这个新函数在 hello_world 函数执行前后分别打印一条消息。我们可以看到,装饰器实际上是一个返回函数的函数。
函数签名保持

默认情况下,装饰器会“掩盖”掉原函数的名字和文档字符串。这是因为在装饰器内部,我们返回了一个全新的函数。我们可以使用 functools.wraps 来解决这个问题:
  1. import functools
  2. def decorator(func):
  3.     @functools.wraps(func)
  4.     def wrapper():
  5.         print('Before function execution')
  6.         func()
  7.         print('After function execution')
  8.     return wrapper
  9. @decorator
  10. def hello_world():
  11.     "Prints 'Hello, world!'"
  12.     print('Hello, world!')
  13. print(hello_world.__name__)
  14. print(hello_world.__doc__)
复制代码
这样,使用装饰器后的函数名和文档字符串能够保持不变。
Python 装饰器的应用实例

装饰器在实际的 Python 编程中有许多应用场景,比如日志记录、性能测试、事务处理、缓存、权限校验等。
一个常见的应用就是使用装饰器进行日志记录:
  1. import logging
  2. def log_decorator(func):
  3.     logging.basicConfig(level=logging.INFO)
  4.    
  5.     def wrapper(*args, **kwargs):
  6.         logging.info(f'Running "{func.__name__}" with arguments {args} and kwargs {kwargs}')
  7.         result = func(*args, **kwargs)
  8.         logging.info(f'Finished "{func.__name__}" with result {result}')
  9.         return result
  10.    
  11.     return wrapper
  12. @log_decorator
  13. def add(x, y):
  14.     return x + y
复制代码
这个装饰器记录了函数的名称,函数调用的参数,以及函数返回的结果。
装饰器链

Python 允许我们将多个装饰器应用到一个函数上,形成一个装饰器链。例如,我们可以同时应用日志装饰器和性能测试装饰器:
  1. import time
  2. import logging
  3. from functools import wraps
  4. def log_decorator(func):
  5.     logging.basicConfig(level=logging.INFO)
  6.    
  7.     @wraps(func)
  8.     def wrapper(*args, **kwargs):
  9.         logging.info(f'Running "{func.__name__}" with arguments {args} and kwargs {kwargs}')
  10.         result = func(*args, **kwargs)
  11.         logging.info(f'Finished "{func.__name__}" with result {result}')
  12.         return result
  13.     return wrapper
  14. def timer_decorator(func):
  15.     @wraps(func)
  16.     def wrapper(*args, **kwargs):
  17.         start_time = time.time()
  18.         result = func(*args, **kwargs)
  19.         end_time = time.time()
  20.         print(f'Function "{func.__name__}" took {end_time - start_time} seconds to run.')
  21.         return result
  22.     return wrapper
  23. @log_decorator
  24. @timer_decorator
  25. def add(x, y):
  26.     time.sleep(2)
  27.     return x + y
复制代码
在这个例子中,@log_decorator 和 @timer_decorator 两个装饰器被同时应用到 add 函数上,它们分别负责记录日志和测量函数运行时间。
One More Thing: 自动注册装饰器

一个有趣的装饰器应用是自动注册。这个装饰器会在装饰函数时自动将函数添加到一个列表或字典中,这样我们就可以在程序的其他地方访问到这个列表或字典,知道有哪些函数被装饰过。
  1. # 装饰器将函数注册到一个列表中
  2. def register_decorator(func_list):
  3.     def decorator(func):
  4.         func_list.append(func)
  5.         return func
  6.     return decorator
  7. # 自动注册函数
  8. registered_functions = []
  9. @register_decorator(registered_functions)
  10. def foo():
  11.     pass
  12. @register_decorator(registered_functions)
  13. def bar():
  14.     pass
  15. print(registered_functions)  # 输出: [<function foo at 0x10d38d160>, <function bar at 0x10d38d1f0>]
复制代码
这个装饰器可以用于自动注册路由、插件系统、命令行参数处理等场景,能够大大提高代码的灵活性和可扩展性。
总结

Python 装饰器是一种强大的工具,它可以让我们更有效地管理和组织代码。希望通过这篇文章,你能够更深入地理解装饰器的工作原理和用法,从而在你的项目中更好地使用装饰器。
如有帮助,请多关注
个人微信公众号:【Python全视角】
TeahLead_KrisChang,10+年的互联网和人工智能从业经验,10年+技术和业务团队管理经验,同济软件工程本科,复旦工程管理硕士,阿里云认证云服务资深架构师,上亿营收AI产品业务负责人。

来源:https://www.cnblogs.com/xfuture/p/17445659.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具