当前位置:首页>python>Python快速入门学习笔记二十:装饰器

Python快速入门学习笔记二十:装饰器

  • 2026-10-11 07:54:59
Python快速入门学习笔记二十:装饰器
❝

Python入门第二十课,主要是学习了装饰器,装饰器是一种在不改变原函数代码的前提下,动态增加函数功能的高级语法糖,提升了代码的复用性与可读性。

  • 什么是装饰器
  • 函数装饰器
  • 类装饰器

什么是装饰器

装饰器是一种在『不修改原函数代码』的前提下,对函数进行『增强』的工具。它是Python中非常强大的语法特性,常用于:日志、校验、计时、缓存、权限控制等。

核心语法:装饰器是一种可调用对象(通常是函数),接收一个函数作为参数,并返回一个函数。

通常分为两个类型:函数装饰器、类装饰器。下面详细介绍。

函数装饰器

❝

需求:在不修改add函数的前提下,给add函数增加一些额外的功能,例如:计算前打印一句欢迎语。

1、定义函数装饰器

defsay_hello(func):
defwrapper(*args, **kwargs):
        print("你好,我要开始计算了")
return func(*args, **kwargs)
return wrapper

定义装饰器核心规则:

  • 接收被装饰的函数、同时返回新函数(wrapper)。
  • 装饰器“吐出来”的是 wrapper 函数,以后别人调用的也是 wrapper 函数。
  • 为了保证参数的兼容性,wrapper 函数通过 *args 和 *kwargs 接收参数。
  • wrapper 函数中主要做的是:调用原函数(被装饰的函数)、执行其它逻辑,但记得将原函数的返回值 return 出去。

2、使用函数装饰器(手动装饰)

defadd(a, b, c):
    res = a + b + c
    print(f'{a}和{b}和{c}相加的结果是:{res}')
return res

# 调用 say_hello 装饰器,对 add 函数进行装饰,并得到装饰后的新函数
add = say_hello(add)
result = add(1, 2, 3)
print(result)

上述代码运行结果:

你好,我要开始计算了
1和2和3相加的结果是:6
6

3、使用函数装饰器(语法糖@)

@say_hello
defadd(a, b, c):
    res = a + b + c
    print(f'{a}和{b}和{c}相加的结果是:{res}')
return res

result = add(1, 2, 3)
print(result)

上述代码运行结果:

你好,我要开始计算了
1和2和3相加的结果是:6
6

上述代码的执行流程:

❝

➀ @say_hello会自动执行:add = say_hello(add)。

➁ 以后调用add()时,真正执行的是wrapper()。

4、带参数的函数装饰器(三层嵌套)

需求:装饰不同的函数,打印不同的欢迎语。

核心:带参数的装饰器最终是三层嵌套:外层接收配置、中间层接收函数、内层接收具体参数。

defcalculate(msg):
defouter(func):
defwrapper(*args, **kwargs):
            print(f'你好,我要开始{msg}计算了')
return func(*args, **kwargs)
return wrapper
return outer

# 装饰加法函数
@calculate('加法')
defadd(a, b, c):
    res = a + b + c
    print(f'{a}和{b}和{c}相加的结果是:{res}')
return res

# 装饰减法函数
@calculate('减法')
defsub(a, b):
    res = a - b
    print(f'{a}和{b}相减的结果是:{res}')
return res

result = add(1, 2, 3)
print(result)

print()

result1 = sub(4, 5)
print(result1)

上述代码运行结果如下:

你好,我要开始加法计算了
1和2和3相加的结果是:6
6

你好,我要开始减法计算了
4和5相减的结果是:-1
-1

5、多个函数装饰器一起使用

核心:注意装饰顺序,距离函数最近的装饰器,会先工作。

例如下面的代码:test2先装饰,test1再装饰。

defdecorator1(func):
    print('我是decorator1装饰器')
defwrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        print('decorator1追加的逻辑')
return res
return wrapper

defdecorator2(func):
    print('我是decorator2装饰器')
defwrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        print('decorator2追加的逻辑')
return res
return wrapper

@decorator1
@decorator2
defadd(a, b, c):
    res = a + b + c
    print(f'{a}和{b}和{c}相加的结果是:{res}')
return res

result = add(1, 3, 4)
print(result)

上述代码运行结果如下:

我是decorator2装饰器
我是decorator1装饰器
1和3和4相加的结果是:8
decorator2追加的逻辑
decorator1追加的逻辑
8

类装饰器

包含__call__方法的类,就是类装饰器。

像调用函数一样,去调用类装饰器的实例对象,就会触发__call__方法的调用。

__call__方法通常接收一个函数作为参数,并且会返回一个新函数。

1、定义类装饰器

需求和之前一样,还是给add函数增加【打印欢迎语】的功能。

classSayHello:
def__call__(self, func):
defwrapper(*args, **kwargs):
            print('你好,我要开始计算了')
return func(*args, **kwargs)
return wrapper

2、使用类装饰器(手动装饰)

手动使用类装饰器的流程:先创建类的实例对象,随后调用实例对象,并传入要装饰的函数。

# 定义被装饰函数
defadd(x, y):
    res = x + y
    print(f'{x}和{y}相加的结果是{res}')
return res

# 使用 SayHello 去装饰 add 函数(手动装饰)
say_hello_inst = SayHello()
add_decorator = say_hello_inst(add)

# 调用装饰后的函数
result = add_decorator(10, 20)
print(result)

# 运行结果如下:
# 你好,我要开始计算了
# 10和20相加的结果是30
# 30

3、使用类装饰器(语法糖@)

注意:通过语法糖@使用装饰器时,类名后要加圆括号调用。

@SayHello()
defadd(x, y):
    res = x + y
    print(f'{x}和{y}相加的结果是{res}')
return res

# 直接调用被装饰的函数 add,但调用的是被装饰后的新函数
result = add(1, 2)
print(result)

# 运行结果如下:
# 你好,我要开始计算了
# 1和2相加的结果是3
# 3

4、带参数的类装饰器(三层嵌套)

带参数的类装饰器写起来,要比带参数的函数装饰器简单,不需要三层结构。

classSayHello:
def__init__(self, msg):
        self.msg = msg

def__call__(self, func):
defwrapper(*args, **kwargs):
            print(f'你好,我要开始{self.msg}计算了')
return func(*args, **kwargs)
return wrapper

@SayHello('加法')
defadd(x, y):
    res = x + y
    print(f'{x}和{y}相加的结果是{res}')
return res

# 直接调用被装饰的函数 add,但调用的是被装饰后的新函数
result = add(1, 2)
print(result)

# 运行结果如下:
# 你好,我要开始加法计算了
# 1和2相加的结果是3
# 3

5、多个类装饰器一起使用

classSayHello:
def__init__(self, msg):
        self.msg = msg

def__call__(self, func):
defwrapper(*args, **kwargs):
            print(f'你好,我要开始{self.msg}计算了')
return func(*args, **kwargs)
return wrapper

classHelper:
def__call__(self, func):
defwrapper(*args, **kwargs):
            print('相信我,绝对可以的')
return func(*args, **kwargs)
return wrapper

@SayHello('加法')
@Helper()
defadd(x, y):
    res = x + y
    print(f'{x}和{y}相加的结果是{res}')
return res

# 直接调用被装饰的函数 add,但调用的是被装饰后的新函数
result = add(1, 2)
print(result)

最新文章

随机文章