装饰器的两三事

装饰器作为Python的语法糖,现在应该已经作为必修知识点了,这一篇是我对于装饰器的一些略微一点点深入思考后,写的一篇总结笔记,欢迎大家讨论
  • 简单说两句装饰器
       装饰器其实在版本迭代和代码重用上,有很明显的作用,但是他的语法形式,其实有一定的独特性,所以很多小伙伴对他只是一知半解。
       其实并没有这么的复杂,这里我就给大家拆开了,一步一步的来研究下装饰器到底是怎么玩的。
    

废话不多说,开搞

def func_1(f):
    """
    这是一个有内部函数的函数
    :param f: 参数f是一个可执行的函数 
    :return: 返回内部函数的地址
    """
    def inner():
        """
        这是一个内部函数,执行f()并返回f()的执行结果,f在上面
        :return:  返回值为函数f的执行结果
        """
        print('this is func1')
        return f()
    return inner

没问题,我们测试一下

# 这是一个简单的函数
def func_2():
    print('func_2')


# 获得内部函数
test_func = func_1(func_2)  # test_func == inner

test_func()  # == inner()

# this is func1
# func_2

结果ok,如果有小伙伴不明白为什么,请一定好好的找一个python教程看一下
好了接下来,我要给我们的测试添加条件
1、不允许修改func_2代码,把func_2这个函数封版,按照开放封闭原则
2、我要以func_2( ) 的形式得到上面输出的结果

看了这两个条件,是不是有点懵,这时候就需要动点小脑筋
  • 条件1说不允许改func_2的代码,好的,我不改,我给他套壳,这时候我们回头单单看一下func_1( )函数,这是不是就是给inner函数套了一个壳
  • 条件2说不允许修改func_2的调用方式,好的,我还是用func_2( )去执行,只不过我把func_2指向inner,那最后执行的其实就是inner(已经套壳的func_2)
完美

好!我们一步一步来
第一步:我先来做个壳,起个名字叫做clothes,(就像穿了件衣服)

def clothes(func):
    def inner():
        return func()

    return inner

简单不

      tips:如果这个还看不懂,请认真复习基础知识,因为这是一个对于任何编程语言,基础架构的理解

第二步:我给这个壳加工一下,以防需要被加壳的函数有参数

def clothes(func):
    def inner(*args, **kwargs):
        return func(*args, **kwargs)

    return inner

这里有一个知识点,(这个知识点我知识测试过,并没有查过文档,但是个人感觉应该没错,错了大佬请拍砖)
*args 如果作为参数传递,他会根据函数声明的个数进行分解
怎么理解?
1、*args是不定参数 他是一个tuple
2、*args不能作为变量来声明,他是函数参数的一个特定参数
如果函数声明是func(a,b,c,d),如果我传给他一个不定参数 *args=(1,2,3,4) 那就会自动去契合,他就会让a=1,b=2,c=3,d=4
注意:
首先,如果你想用*args去给另一个函数传参数,请匹配那个函数的参数个数
第二点,由于不能用*args去声明变量,那*args只能在函数内部传递,那就说明,你只能给内部函数传递*args
这里先这样,大家可以自己尝试下
继续
第三步:让壳去做点自己想做的事情

def clothes(func):
    def inner(*args, **kwargs):
        print('I am a cloth')
        return func(*args, **kwargs)

    return inner

第四步:我们给函数套壳

def func_2(str1):
    print(str1)

func_2 = clothes(func_2)
func_2('111')
# I am a cloth
# 111

这时候,func_2已经被套壳了,func_2 == inner
套壳完成!
第一次看可能有点绕,我给大家往白了说,func_2 就是用来获取clothes函数的返回值,那如果返回是个int呢?

def clothes(func):
    def inner(*args, **kwargs):
        print('I am a cloth')
        return func(*args, **kwargs)

    return 1  # int


func_2 = clothes(func_2)
print(func_2)
# 1

这么一看是不是就看明白了

这就是装饰器的原理,并且装饰器给了我们一个更方便的语法

def clothes(func):
    def inner(*args, **kwargs):
        print('I am a cloth')
        return func(*args, **kwargs)

    return inner


@clothes
def func_2(a):
    print(a)


func_2(111)

@clothes就是装饰器,把他按在一个函数之上,就代表要用下方函数地址作为参数,传递给装饰器函数,然后返回再返回给被装饰的函数(也就是func_2)
这时候你再调用func_2函数就会达到,不修改函数内部,也不修改函数调用方法,就能修改函数功能的作用

基本功能做完,我们再加深一下,能不能给inner函数传个参数
上面我是打印了一句话 print(‘I am a cloth’) 这次我想打印 print(data) data是个变量
我先给代码,大家先结合上面的原理看一看

def out(data):
    def clothes(func):
        def inner(*args, **kwargs):
            print(data)
            return func(*args, **kwargs)

        return inner
    return clothes


@out("abcd")
def func_2(a):
    print(a)

我给个过程提示:@out(“abcd”)得拆开
@+out(“abcd”)
1、tmp_func = out(“abcd”)
2、@tmp_func
理解了吧
@看做一个运算符,右边如果还是一个需要进行运算的结果,类似 int(str(‘a’))

好了,就这样吧,其实装饰器之前我有所了解,但是原理上还是有点问题,所以拖了好久。如果有还有问题,欢迎讨论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值