Python装饰器详解:从闭包到类装饰器的完整指南

栗子
栗子
发布时间:2026-10-15 | 5人浏览过
原创

本文深入解析Python装饰器的核心原理,从闭包的基础概念讲起,逐步演示无参、带参及类装饰器的具体实现。通过实际代码案例,展示如何在无需修改原函数代码的前提下,为函数添加调试、日志记录等额外功能,帮助开发者掌握装饰器的灵活应用技巧。

一、闭包

理解装饰器的前提是掌握闭包这一概念。简单来说,闭包是指在函数内部定义另一个函数,且内部函数引用了外部函数的变量。为了直观理解,我们直接通过代码示例来说明。


def outer(x):
    def inner(y):
        return x + y
    return inner

print(outer(6)(5))
-----------------------------
>>>11

如代码所示,在outer函数内部定义了inner函数,且inner函数引用了外部函数outer的变量x,这构成了一个闭包。执行outer(6)(5)时,第一个括号传入的值返回inner函数,即返回6 + y的逻辑,因此再传入第二个参数即可得到最终返回值6 + 5。

二、装饰器

接下来介绍装饰器,其实装饰器本质上就是一个闭包,它是闭包的一种具体应用。所谓装饰器,简单来说就是用于扩展原函数功能的一种函数,其特殊之处在于返回值仍然是一个函数。使用Python装饰器的好处在于,无需修改原函数的代码即可为其增加新功能。使用时,只需在目标函数前加上@demo即可。


def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

@debug
def hello():
    print("hello")

hello()
-----------------------------
>>>[DEBUG]: enter hello()
>>>hello

示例中的装饰器为函数添加了进入时的debug模式,无需修改原函数代码便实现了该功能,非常便捷。

三、带参数的装饰器

上述示例中的装饰器功能较为简单,那么装饰器是否可以接收参数呢?答案是可以的。此外,被装饰的函数同样可以传递参数。


def logging(level):
    def outwrapper(func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(level, func.__name__))
            return func(*args, **kwargs)
        return wrapper
    return outwrapper

@logging(level="INFO")
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[INFO]: enter hello()
>>>hello, good morning

如上所示,装饰器中可以传入参数,先构建一个完整的装饰器,然后再用于装饰函数。如果被装饰的函数需要传入参数,也可以使用不定长参数符号来接收,示例中传入了三个参数。

四、类装饰器

装饰器不仅可以用函数编写,还可以使用类来实现,即类装饰器。其用法与函数装饰器没有太大区别,实质是利用类方法中的__call__魔法方法来实现类的直接调用。


class logging(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("[DEBUG]: enter {}()".format(self.func.__name__))
        return self.func(*args, **kwargs)

@logging
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[DEBUG]: enter hello()
>>>hello, good morning

类装饰器同样可以携带参数,如下所示的实现方式。


class logging(object):
    def __init__(self, level):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(self.level, func.__name__))
            return func(*args, **kwargs)
        return wrapper
        
@logging(level="TEST")
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[TEST]: enter hello()
>>>hello, good morning

以上就是装饰器的一些基本概念和大致用法。若想更深入地理解装饰器,还需要在日常练习和应用中多加体会。

以上就是如何正确理解python装饰器的详细内容,更多关于python装饰器的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表