python高阶应用——装饰器

Python 中的装饰器

在 Python 中,装饰器是一种非常强大的功能,它允许你在不修改原有函数定义的情况下增加函数的功能。装饰器通常用于日志记录、性能测试、事务处理、缓存、权限校验等场景。

1.基本装饰器

一个装饰器本质上是一个 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()

输出将会是:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

在这个例子中,my_decorator 是一个装饰器,它内部定义了一个 wrapper 函数。wrapper 函数会在 func 被调用前后打印一些信息。通过在 say_hello 函数前面加上 @my_decorator,我们实际上是将 say_hello 函数传递给了 my_decorator,并将返回的 wrapper 函数赋值给 say_hello

2. 装饰器接受参数

如果你的函数需要接受参数,装饰器需要相应地进行调整:

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

@my_decorator
def say(message):
    print(message)

say("Hello with argument")

在这个例子中,wrapper 函数使用 *args**kwargs 来接受任意数量的位置参数和关键字参数,并将它们传递给 func 函数。

3.装饰器带有自己的参数

装饰器也可以带有自己的参数,这需要使用一个额外的函数层来接受这些参数:

def repeat(number_of_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(number_of_times):
                func(*args, **kwargs)
        return wrapper
    return decorator_repeat

@repeat(number_of_times=3)
def say(message):
    print(message)

say("Hello repeated")

在这个例子中,repeat 函数是一个装饰器工厂,它创建并返回一个装饰器。这个装饰器接受一个函数并返回 wrapper 函数。wrapper 函数将会重复调用 func 函数指定的次数。

4.使用 functools.wraps

当你使用装饰器时,你实际上是用另一个函数 wrapper 替换了原始的函数。这意味着原始函数的一些信息,如它的名字、文档字符串、注解和模块信息会丢失。为了避免这种情况,你可以使用 functools.wraps,它会保留原始函数的信息:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """Wrapper function"""
        print("Something is happening before the function is called.")
        func(*args, **kwargs)
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    """Say hello function"""
    print("Hello!")

print(say_hello.__name__)  # 输出 "say_hello"
print(say_hello.__doc__)   # 输出 "Say hello function"

通过使用 functools.wrapssay_hello 函数保留了它的元数据,而不是显示 wrapper 函数的元数据。

装饰器是 Python 中一个非常强大的特性,可以用来简洁地修改函数的行为。通过掌握装饰器,你可以编写出更加干净、优雅和可复用的代码。

拓展: 可变参数:*args**kwargs

在 Python 中,*args**kwargs 是处理函数可变参数的特殊语法。

  • *args(arguments 的缩写)允许函数接收不确定数量的位置参数。这些参数在函数内部被视为一个元组。
  • **kwargs(keyword arguments 的缩写)允许函数接收不确定数量的`关键字参数。这些参数在函数内部被视为一个字典。
使用 *args**kwargs 的例子
def my_function(*args, **kwargs):
    print("args:", args)
    print("kwargs:", kwargs)

my_function(1, 2, 3, name="John", age=25)
输出:
args: (1, 2, 3)
kwargs: {'name': 'John', 'age': 25} 

在装饰器中使用 *args**kwargs

*args**kwargs 在装饰器中非常有用,因为它们允许 wrapper 函数传递任意数量的参数给被装饰的函数。

下面是一个使用 *args**kwargs 的装饰器示例:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        # 在原始函数调用前做一些事情
        result = func(*args, **kwargs)
        # 在原始函数调用后做一些事情
        return result
    return wrapper

这个装饰器中的 wrapper 函数可以接收任意数量的位置参数和关键字参数,并将它们传递给被装饰的函数 func。这样,不管 func 需要哪些参数,wrapper 都能正确地传递这些参数。

  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值