python的装饰器

作用:
    在不改变原来函数的代码情况下,进行修改,或者增加函数的功能
    装饰器本质上就是一个闭包

雏形:
    def  wrapper(fn):   wrapper: 装饰器 , fn: 目标函数
        def inner():
             # 在目标函数执行前的一些动作
             fn()
             # 在目标函数执行后的一些动作

        return inner   #千万别加(),这里是返回一个函数名。如果加(),表示返回函数执行的结果

    @wrapper
    def fn():   #目标函数    
        print("xxxxxxx")
   

功能:

    执行目标函数fn, 相当于执行了wrapper函数里闭包的inner函数过程
1. 装饰器方式一

def lunch(fuc):
    def inner():
        print("water hand")
        fuc()
        print("su kou")
    return inner


def eat():
    print("eat somethings")

lunch(eat) #这里返回是一个函数名inner,函数名在内存中指向一个地址
l = lunch(eat)  # l 和 inner 同时指向同一个内存地址
l()  #这里是执行inner函数体


#执行结果
water hand
eat somethings
su kou

2.装饰器方式二


def lunch(fuc):
    def inner():
        print("water hand")   #在执行eat()函数前需要增加的动作
        fuc()    #这里是lunch函数的形参,将以eat函数名作为形参,这里就是执行eat()函数一样。
        print("su kou")   #在执行eat()函数前需要增加的动作
    return inner


@lunch   # 这里相当于eat = lunch(eat),由于lunch(eat)返回inner函数名,相当于eat()执行,就换成inner()执行一样。
def eat():
    print("eat somethings")


#执行eat()函数体,相当于调用lunch的函数,把eat函数名作为lunch函数的形参fuc传入,在不改变eat函数本身的代码,增加了一些功能


eat()  #执行eat() 


总结:
    上面两种方法,都是可以,但是看自己的需求

二。扩展

def lunch(fuc):
    def inner(name, number):  #使用装饰器后,执行eat函数相当于执行inner函数,那这里也要有两个形参
        print("water hand")
        fuc(name, number)   #在执行inner函数时,这个是调用目标eat函数,由于下面eat函数定义有两个实参,因此这里也要有对应的形参,并且数量要一样
        print("su kou")

    return inner


@lunch
def eat(name, num): #这里函数有实参
    print("吃{}水果,吃了{}个".format(name, num))


#如果eat有定义实参,而装饰器没有定义形参,就会报错类似这样,# TypeError: inner() takes 0 positional arguments but 2 were given
eat("apple",5) 

执行结果:
   water hand
   吃apple水果,吃了5个
   su kou


三,扩展三

1.如果这个food装饰器要被多个函数调用,并且是同一个功能,并且多个函数的实参是不一样的,因此就需要使用*args,来接收实参。这样不管调用这个装饰器的函数,实参多少个都可以匹配,

def food(fnc):
    def inner(*args):  #多个形参
        print("water hand")
        fnc(*args)     #多个形参
        print("su kou")
    return inner

@food
def drink(name, num, money): #三个实参
    print("喝了{}酒,喝了{}瓶,一共花了{}块钱。".format(name, num, money))

drink("葡萄", 10, 8888)


@food
def eat(name, num):  #两个实参
    print("吃{}水果,吃了{}个".format(name, num))

eat("榴莲",3)   


#执行结果

water hand
喝了葡萄酒,喝了10瓶,一共花了8888块钱。
su kou
water hand
吃榴莲水果,吃了3个
su kou

四。扩展四

1:下面的*args, **kwargs,这里不管位置形参,还是关键字形参都包含了,表示0个,或者多个形参匹配

注意要点:
  *args, **kwargs前面的 * 或者 ** ,表示把args元组和kwargs字典打散成位置参数 ,以及关键字参数传递进去,并不是说args看成一个元组作为参数传递进去。

def food(fnc):
    def inner(*args, **kwargs):
        print("water hand")
        fnc(*args, **kwargs)
        print("su kou")
    return inner

@food
def drink(name, num, money):
    print("喝了{}酒,喝了{}瓶,一共花了{}块钱?".format(name, num, money))


drink("葡萄", 10, 8888)  #上面*args, **kwargs,表示匹配0个或者多个位置形参,关键字形参,所以你这里没有定义关键字实参,也是对的

drink("葡萄", 10, money=8888)  #定义关键字实参,

@food
def eat(name, num):
    print("吃{}水果,吃了{}个".format(name, num))

eat("榴莲",3)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值