Python中的“@”,有什么用?

前言

在Python中,@ 符号确实扮演了一个极其重要且富有创意的角色,它以一种优雅的方式引入了“装饰器”(Decorators)这一强大概念,堪称Python编程语言的“语法糖”典范。装饰器不仅增强了代码的可读性和复用性,还允许开发者在不修改原有函数或类定义的情况下,为它们添加新的功能。接下来,我们将深入剖析装饰器的工作原理,并通过一系列示例代码来直观展示其强大之处,从而帮助您更好地理解和运用这一Python特性。
在这里插入图片描述

正文

要知道,在Python中,@ 符号独具特色地应用于函数定义之前,这一机制被巧妙地命名为“装饰器”。装饰器为Python编程带来了极大的灵活性和便利性,它允许开发者以一种非侵入式的方式,为函数或方法增添额外的功能或修改其行为,而无需直接修改函数本身的代码。

举个例子,如下所示:


@print
def say_hello():
    print("Hello, world!")

say_hello()

当成功运行上述代码之后,输出结果如下所示:

<function say_hello at 0x7f6a1c0c8940>

出现上面的情况是什么原因造成的呢?需要注意的是,这里的@print其实是将say_hello函数“装饰”或“包装”了一层print。换言之,这里的say_hello=print(say_hello)被隐藏的执行了。

有同学可能会问,既然用到装饰器,那它的内部机制的工作原理是怎么样的呢?

1.定义装饰器的函数;

2.将装饰器应用于目标函数;

3.在运行的时候替换目标函数。

我们以下面的代码为例,示例如下所示:

def uppercase(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

@uppercase
def say_hello(name):
    return f"hello, {name}"

print(say_hello("Alice"))  # HELLO, ALICE

在上述代码中,定义一个装饰器函数 uppercase,该函数旨在接收另一个函数 func 作为参数,并返回一个新的函数 wrapper。通过使用 @uppercase 语法,我们可以优雅地将 uppercase 装饰器应用于任何期望其返回值被转换为大写的函数上,比如 say_hello 函数。这一过程实质上是将 say_hello 函数作为参数传递给 uppercase 函数,并将 uppercase 返回的新函数 wrapper 重新赋值给 say_hello 的标识符。

当执行 say_hello(“Alice”) 调用时,实际上触发的是经过 uppercase 装饰后的 wrapper 函数。wrapper 函数内部会先调用原始的 say_hello 函数,随后将其返回的字符串转换为大写,最后返回这个转换后的结果。通过这种非侵入式的方式,我们在不直接修改 say_hello 函数体的情况下,为其增添了新的功能特性——即自动将输出转换为大写。这正是装饰器模式在Python中展现其强大灵活性的一个典型示例。

接下来,我们再看看带参数的装饰器。

有的时候,我们需要为装饰器添加一些参数,对此需要怎么去实现呢?我们直接看下面的示例代码:

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            return result * n
        return wrapper
    return decorator

@repeat(3)
def say_hello(name):
    return f"hello, {name}"

print(say_hello("Alice"))  
# hello, Alice hello, Alice hello, Alice

在上面的示例中,repeat 函数扮演了一个“装饰器工厂”的角色,它本身不直接作为装饰器使用,而是根据提供的参数(本例中为重复次数 n)动态生成一个装饰器函数 decorator。这个 decorator 函数随后接受一个目标函数 func 作为参数,并返回一个新的封装函数 wrapper。wrapper 函数的核心职责是在内部调用原始的 func 函数,并巧妙地将 func 的返回值重复 n 次后返回。

利用 @repeat(3) 这样的语法糖,我们得以将 say_hello 函数与 repeat(3) 生成的装饰器无缝结合,实现了一个非侵入式的功能增强:每当调用 say_hello 函数时,其返回的字符串将会被自动重复三次。这一机制展示了装饰器模式在Python中的高度灵活性和强大功能,允许开发者以简洁优雅的方式扩展函数行为。

通过本文,我们深入剖析了Python中@符号背后的内部运作原理与精妙机制。揭示了@符号作为语法糖的本质,它实际上在代码执行前被Python解释器自动转换为一系列函数调用和赋值操作的序列。我们详细阐述了如何定义装饰器函数,展示了如何将装饰器优雅地应用于目标函数之上,并深入探讨了这一过程中如何在运行时动态地替换目标函数的行为。通过这些,可以让你对Python中@符号所蕴含的强大功能与灵活性有更加深刻而全面的认识。

最后 如果你对Python感兴趣的话,可以试试我整理的这份Python全套学习资料,【点击这里】领取!

包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、自动化办公等学习教程。带你从零基础系统性的学好Python!
Python所有方向的学习路线图,清楚各个方向要学什么东西
100多节Python课程视频,涵盖必备基础、爬虫和数据分析
100多个Python实战案例,学习不再是只会理论
华为出品独家Python漫画教程,手机也能学习
历年互联网企业Python面试真题,复习时非常方便******

在这里插入图片描述

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值