python-装饰器的详解和使用

本文深入探讨了装饰器的概念、使用场景及其实现方式,通过实例展示了如何利用装饰器扩展函数功能,遵循开闭原则,简化代码并提高维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、什么是装饰器?

装饰器就是 @函数名 ,加在被装饰函数之前。有时候我们需要对函数功能进行扩展,但是又必须遵守开闭原则(ocp),不能修改函数,这时候就需要使用装饰器。

2、为什么要使用装饰器?

事实上,当我们想要扩展函数功能或者修改函数时,直接修改函数中的某几行代码就可以实现。

但是这是有弊端的。

  • 例如我想给一大批的函数加上同一个功能,那么我需要更改的就不是几行代码了,工作非常繁琐。
  • 也不方便后期进行维护
  • 会违反开闭原则(程序设计要求开发对程序的扩展,要关闭对程序的修改)

综合以上三点,这里我们使用装饰器就再好不过了。

3、装饰器的使用

直接举个例子,给每一个函数在执行前,打印出该函数的名字。

首先看一下没有装饰器的话,我们怎么实现?

def add(*arg):
    print(f'{arg}的和是{sum(arg)}')
    
def print_self(func):
    def bedeco(*arg):
        print(f'我是{func.__name__}函数^-^')
        func(*arg)
    return bedeco
f = print_self
f(add)(1,2,3)

'''
out:
我是add函数^-^
(1, 2, 3)的和是6

整个流程是这样的:
首先定义一个函数,把需要被装饰的函数作为参数接受。然后定义一个内部函数,加上我们装饰的内容,同时调用被装饰的函数,实现其功能,还要把这个函数作为返回值return。(注意不同函数的参数不尽相同,这里用不定长参数*args,**kwargs进行统一)
装饰是完成了,但是使用起来过于繁琐。

再来看看装饰器怎么实现:

def print_self(func):
    def bedeco(*arg):
        print(f'我是{func.__name__}函数^-^')
        func(*arg)
    return bedeco
@print_self
def add(*arg):
    print(f'{arg}的和是{sum(arg)}')

add(1,2,3)

'''
out:
我是add函数^-^
(1, 2, 3)的和是6
'''

同样的结果,只需要在被装饰函数的定义前面加上装饰器即可。

事实上,在调用被装饰函数add之前,add已经变成了print_self(test),也就是装饰器的返回值bedeco。之后在调用add时,add()就相当于bedeco()了,执行的时装饰器的内部函数。

4、总结

  • 通过使用装饰器,我们可以在不修改函数的情况下来扩展功能。
  • 实际在开发中,我们都是通过使用装饰器来扩展函数功能的。
  • 装饰器函数传入的参数必须被装饰函数的对象作为形参,返回值必须是内部函数的象。

5、发散:多个装饰器的装饰顺序

这里我们可以举个例子来试验一下:

def deco1(func):
    def excute():
        return "<装饰1 "+func()+"装饰1 >"
    return excute
def deco2(func):
    def excute():
        return "<装饰2 "+func()+"装饰2 >"
    return excute
@deco1
@deco2
def hello():
    return 'hello world'
hello()

'''
out:
'<装饰1 <装饰2 hello world装饰2 >装饰1 >'
'''

这里我认为真相只有一个,那就是离被装饰函数近的装饰器先装饰。

再来验证一下,这次我多做几个装饰器:

def deco1(func):
    def excute():
        return "<装饰1 "+func()+"装饰1 >"
    return excute
def deco2(func):
    def excute():
        return "<装饰2 "+func()+"装饰2 >"
    return excute
def deco3(func):
    def excute():
        return "<装饰3 "+func()+"装饰3 >"
    return excute
def deco4(func):
    def excute():
        return "<装饰4 "+func()+"装饰4 >"
    return excute
def deco5(func):
    def excute():
        return "<装饰5 "+func()+"装饰5 >"
    return excute
@deco1
@deco2
@deco3
@deco4
@deco5
@deco5
def hello():
    return 'hello world'
hello()

'''
out:
'<装饰1 <装饰2 <装饰3 <装饰4 <装饰5 <装饰5 hello world装饰5 >装饰5 >装饰4 >装饰3 >装饰2 >装饰1 >'
'''

这次我认为原因显然易见了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值