首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Python之装饰器

  • 23-11-14 09:43
  • 3789
  • 11743
blog.csdn.net

Python之装饰器

文章目录

  • Python之装饰器
    • Python之装饰器
    • Python中的标准装饰器
    • 10个非常简单但是却很有用的自定义装饰器
      • 1、@timer:测量执行时间
      • 2、@memoize:缓存结果
      • 3、@validate_input:数据验证
      • 4、@log_results:日志输出
      • 5、@suppress_errors:优雅的错误处理
      • 6、@validate_output:确保质量结果
      • 7、@retry:重试执行
      • 8、@visualize_results:漂亮的可视化
      • 9、@debug:调试变得更容易
      • 10、@deprecated:处理废弃的函数
      • 总结

Python之装饰器

Python中的装饰器是一种高级语法特性,它允许你在不修改原函数源代码的情况下,对函数的行为进行扩展或修改。装饰器本质上是一个接受函数对象作为参数的可调用对象(通常是一个函数),并返回一个新的函数对象。

Python装饰器的基本语法是使用@语法糖将装饰器应用于函数。以下是装饰器的基本示例:

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这个例子中,我们定义了一个名为my_decorator的装饰器。当将其应用于say_hello函数时,该装饰器会在调用say_hello函数之前和之后分别输出一条消息。最后,当我们调用say_hello函数时,我们将看到如下输出:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.
  • 1
  • 2
  • 3

除了以上的简单示例,Python装饰器还可以用于实现各种高级功能,如性能分析、缓存、权限验证等。

Python中的标准装饰器

Python中的标准装饰器是内置的装饰器,用于对函数或方法进行装饰,以实现特定的功能或修改其行为。以下是Python中的一些标准装饰器:

  1. @wraps:该装饰器用于保留被装饰函数的元信息(如名称、文档字符串、模块等),并在调用被装饰函数时将其传递给装饰器函数。
  2. @functools.wraps:该装饰器与@wraps相同,但还具有一些额外的功能,如参数化装饰器和部分装饰器。
  3. @staticmethod:该装饰器用于创建不依赖于类实例的方法,即该方法不需要访问类实例的属性或方法。
  4. @classmethod:该装饰器用于创建依赖于类实例的方法,即该方法需要访问类实例的属性或方法。
  5. @property:该装饰器用于将一个方法转换为属性,以便在类实例上使用。
  6. @types.coroutine:该装饰器用于将一个生成器函数转换为协程函数,以便使用异步编程功能。
  7. @asyncio.coroutine:该装饰器用于将一个生成器函数转换为协程函数,以便使用异步编程功能,但在Python 3.7之后被废弃,应该使用@types.coroutine。
  8. @types.generator:该装饰器用于将一个函数转换为生成器函数。
  9. @contextlib.contextmanager:该装饰器用于将一个生成器函数或具有__enter__和__exit__方法的对象转换为上下文管理器。
  10. @functools.singledispatch:该装饰器用于根据第一个参数的类型对函数进行分派,以便实现多态行为。

这些标准装饰器可以帮助您在Python中编写更简洁、易于理解和维护的代码。

好的,我来分别举例说明这些标准装饰器:

  1. @wraps:该装饰器可以保留被装饰函数的元信息,并在调用被装饰函数时将其传递给装饰器函数。例如:
from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Before the function is called.")
        result = func(*args, **kwargs)
        print("After the function is called.")
        return result
    return wrapper

@my_decorator
def add(x, y):
    return x + y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在上面的例子中,@wraps保留了add函数的元信息,并在调用add函数时将其传递给装饰器函数。

  1. @functools.wraps:该装饰器与@wraps相同,但还具有一些额外的功能,如参数化装饰器和部分装饰器。例如:
from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Before the function is called.")
        result = func(*args, **kwargs)
        print("After the function is called.")
        return result
    return wrapper
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在上面的例子中,@wraps保留了add函数的元信息,并在调用add函数时将其传递给装饰器函数。这个装饰器并没有使用参数化装饰器或部分装饰器的功能。

  1. @staticmethod:该装饰器用于创建不依赖于类实例的方法,即该方法不需要访问类实例的属性或方法。例如:
class MyClass(object):
    @staticmethod
    def my_method(x, y):
        return x + y
  • 1
  • 2
  • 3
  • 4

在上面的例子中,my_method是一个静态方法,它不依赖于类实例,可以直接通过类名调用。

  1. @classmethod:该装饰器用于创建依赖于类实例的方法,即该方法需要访问类实例的属性或方法。例如:
class MyClass(object):
    @classmethod
    def my_method(cls, x, y):
        return cls.__name__ + ": " + str(x + y)
  • 1
  • 2
  • 3
  • 4

在上面的例子中,my_method是一个类方法,它依赖于类实例,可以通过类名或类实例调用。它访问了类实例的属性(cls)和方法(name)。

好的,以下是剩余的几个标准装饰器的例子:

  1. @property:该装饰器用于将一个方法转换为属性,以便在类实例上使用。例如:
class MyClass(object):
    def __init__(self, value):
        self._value = value
    
    @property
    def value(self):
        return self._value
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在上面的例子中,value被装饰为一个属性,可以通过类实例直接访问。

  1. @types.coroutine:该装饰器用于将一个生成器函数转换为协程函数,以便使用异步编程功能。例如:
import asyncio
from types import coroutine

@coroutine
def my_coroutine():
    print("Before the yield statement.")
    yield
    print("After the yield statement.")

async def main():
    print("Before the coroutine is called.")
    my_coroutine()
    print("After the coroutine is called.")

asyncio.run(main())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在上面的例子中,my_coroutine被装饰为一个协程函数,可以通过asyncio库中的run()函数调用。它使用yield语句来暂停和恢复执行。

  1. @asyncio.coroutine:该装饰器用于将一个生成器函数转换为协程函数,以便使用异步编程功能,但在Python 3.7之后被废弃,应该使用@types.coroutine。例如:
import asyncio
from functools import wraps
from types import coroutine

@coroutine
@wraps(my_coroutine)
def my_coroutine_wrapper():
    print("Before the yield statement.")
    yield from my_coroutine()
    print("After the yield statement.")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

好的,以下是剩余的几个标准装饰器的例子:

  1. @types.generator:该装饰器用于将一个函数转换为生成器函数。例如:
import types

def my_generator():
    yield 1
    yield 2
    yield 3

def my_function():
    for i in my_generator():
        print(i)

my_function()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在上面的例子中,my_generator被装饰为一个生成器函数,可以通过for循环迭代并使用yield语句生成值。my_function函数使用for循环来迭代my_generator中的值。

  1. @contextlib.contextmanager:该装饰器用于将一个生成器函数或具有__enter__和__exit__方法的对象转换为上下文管理器。例如:
import contextlib

@contextlib.contextmanager
def my_context_manager():
    print("Before the context.")
    try:
        yield
    finally:
        print("After the context.")

with my_context_manager():
    print("Inside the context.")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在上面的例子中,my_context_manager被装饰为一个上下文管理器,使用with语句来进入和退出上下文。在上下文中,my_context_manager会打印出"Before the context.“和"After the context.”,而"Inside the context."则会被打印出来。

  1. @functools.singledispatch:该装饰器用于根据第一个参数的类型对函数进行分派,以便实现多态行为。例如:
from functools import singledispatch

@singledispatch
def my_dispatcher(arg):
    raise NotImplementedError(f"Unsupported type: {type(arg).__name__}")

@my_dispatcher.register(int)
def _(arg):
    print("Processing an integer.")

@my_dispatcher.register(str)
def _(arg):
    print("Processing a string.")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在上面的例子中,my_dispatcher是一个分派函数,它根据第一个参数的类型注册不同的处理函数。当调用my_dispatcher时,它会根据第一个参数的类型选择正确的处理函数来执行。这个例子中注册了两个处理函数,一个用于处理整数,另一个用于处理字符串。

10个非常简单但是却很有用的自定义装饰器

装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用于在不修改原始代码的情况下添加额外的功能或功能。

装饰器的语法使用@符号,将装饰器应用于目标函数或类。下面我们将介绍10个非常简单但是却很有用的自定义装饰器。

1、@timer:测量执行时间

优化代码性能是非常重要的。@timer装饰器可以帮助我们跟踪特定函数的执行时间。通过用这个装饰器包装函数,我可以快速识别瓶颈并优化代码的关键部分。下面是它的工作原理:

import time

def timer(func):
	def wrapper(*args, **kwargs):
		start_time = time.time()
		result = func(*args, **kwargs)
		end_time = time.time()
		print(f"{func.__name__} took {end_time - start_time:.2f} seconds to execute.")
		return result
	return wrapper

@timer
def my_data_processing_function():
	# Your data processing code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

将@timer与其他装饰器结合使用,可以全面地分析代码的性能。

2、@memoize:缓存结果

在数据科学中,我们经常使用计算成本很高的函数。@memoize装饰器帮助我缓存函数结果,避免了相同输入的冗余计算,显著加快工作流程:

def memoize(func):
	cache = {}
    def wrapper(*args):
        if args in cache:
            return cache[args]
        result = func(*args)
        cache[args] = result
        return result
	return wrapper

@memoize
def fibonacci(n):
	if n <= 1:
		return n
	return fibonacci(n - 1) + fibonacci(n - 2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在递归函数中也可以使用@memoize来优化重复计算。

3、@validate_input:数据验证

数据完整性至关重要,@validate_input装饰器可以验证函数参数,确保它们在继续计算之前符合特定的标准:

def validate_input(func):
	def wrapper(*args, **kwargs):
		# Your data validation logic here
		if valid_data:
			return func(*args, **kwargs)
		else:
			raise ValueError("Invalid data. Please check your inputs.")

		return wrapper

@validate_input
def analyze_data(data):
	# Your data analysis code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以方便的使用@validate_input在数据科学项目中一致地实现数据验证。

4、@log_results:日志输出

在运行复杂的数据分析时,跟踪每个函数的输出变得至关重要。@log_results装饰器可以帮助我们记录函数的结果,以便于调试和监控:

def log_results(func):
	def wrapper(*args, **kwargs):
		result = func(*args, **kwargs)
		with open("results.log", "a") as log_file:
		log_file.write(f"{func.__name__} - Result: {result}
")
		return result
	return wrapper

@log_results
def calculate_metrics(data):
	# Your metric calculation code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

将@log_results与日志库结合使用,以获得更高级的日志功能。

5、@suppress_errors:优雅的错误处理

数据科学项目经常会遇到意想不到的错误,可能会破坏整个计算流程。@suppress_errors装饰器可以优雅地处理异常并继续执行:

def suppress_errors(func):
	def wrapper(*args, **kwargs):
		try:
			return func(*args, **kwargs)
		except Exception as e:
			print(f"Error in {func.__name__}: {e}")
		return None
	return wrapper

@suppress_errors
def preprocess_data(data):
	# Your data preprocessing code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

@suppress_errors可以避免隐藏严重错误,还可以进行错误的详细输出,便于调试。

6、@validate_output:确保质量结果

确保数据分析的质量至关重要。@validate_output装饰器可以帮助我们验证函数的输出,确保它在进一步处理之前符合特定的标准:

def validate_output(func):
	def wrapper(*args, **kwargs):
		result = func(*args, **kwargs)
		if valid_output(result):
			return result
		else:
			raise ValueError("Invalid output. Please check your function logic.")
	return wrapper

@validate_output
def clean_data(data):
	# Your data cleaning code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这样可以始终为验证函数输出定义明确的标准。

7、@retry:重试执行

@retry装饰器帮助我在遇到异常时重试函数执行,确保更大的弹性:

import time

def retry(max_attempts, delay):
	def decorator(func):
		def wrapper(*args, **kwargs):
			attempts = 0
			while attempts < max_attempts:
				try:
					return func(*args, **kwargs)
				except Exception as e:
					print(f"Attempt {attempts + 1} failed. Retrying in {delay} seconds.")
				attempts += 1
				time.sleep(delay)
				raise Exception("Max retry attempts exceeded.")
		return wrapper
	return decorator

@retry(max_attempts=3, delay=2)
def fetch_data_from_api(api_url):
	# Your API data fetching code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

使用@retry时应避免过多的重试。

8、@visualize_results:漂亮的可视化

@visualize_results装饰器数据分析中自动生成漂亮的可视化结果

import matplotlib.pyplot as plt

def visualize_results(func):
	def wrapper(*args, **kwargs):
		result = func(*args, **kwargs)
		plt.figure()
		# Your visualization code here
		plt.show()
		return result
	return wrapper

@visualize_results
def analyze_and_visualize(data):
	# Your combined analysis and visualization code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

9、@debug:调试变得更容易

调试复杂的代码可能非常耗时。@debug装饰器可以打印函数的输入参数和它们的值,以便于调试:

def debug(func):
	def wrapper(*args, **kwargs):
		print(f"Debugging {func.__name__} - args: {args}, kwargs: {kwargs}")
		return func(*args, **kwargs)
	return wrapper

@debug
def complex_data_processing(data, threshold=0.5):
	# Your complex data processing code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

10、@deprecated:处理废弃的函数

随着我们的项目更新迭代,一些函数可能会过时。@deprecated装饰器可以在一个函数不再被推荐时通知用户:

import warnings

def deprecated(func):
	def wrapper(*args, **kwargs):
		warnings.warn(f"{func.__name__} is deprecated and will be removed in future versions.", 					DeprecationWarning)
		return func(*args, **kwargs)
	return wrapper


@deprecated
def old_data_processing(data):
	# Your old data processing code here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

总结

装饰器是Python中一个非常强大和常用的特性,它可以用于许多不同的情况,例如缓存、日志记录、权限控制等。通过在项目中使用的我们介绍的这些Python装饰器,可以简化我们的开发流程或者让我们的代码更加健壮。

《AUTOSAR谱系分解(ETAS工具链)》之总目录

注:本文转载自blog.csdn.net的PlutoZuo的文章"https://blog.csdn.net/PlutoZuo/article/details/134317739"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top