• python的装饰器


    1. 作用:
    2. 在不改变原来函数的代码情况下,进行修改,或者增加函数的功能
    3. 装饰器本质上就是一个闭包
    4. 雏形:
    5. def wrapper(fn): wrapper: 装饰器 , fn: 目标函数
    6. def inner():
    7. # 在目标函数执行前的一些动作
    8. fn()
    9. # 在目标函数执行后的一些动作
    10. return inner #千万别加(),这里是返回一个函数名。如果加(),表示返回函数执行的结果
    11. @wrapper
    12. def fn(): #目标函数
    13. print("xxxxxxx")
    14. 功能:
    15. 执行目标函数fn, 相当于执行了wrapper函数里闭包的inner函数过程
    1. 1. 装饰器方式一
    2. def lunch(fuc):
    3. def inner():
    4. print("water hand")
    5. fuc()
    6. print("su kou")
    7. return inner
    8. def eat():
    9. print("eat somethings")
    10. lunch(eat) #这里返回是一个函数名inner,函数名在内存中指向一个地址
    11. l = lunch(eat) # l 和 inner 同时指向同一个内存地址
    12. l() #这里是执行inner函数体
    13. #执行结果
    14. water hand
    15. eat somethings
    16. su kou

    1. 2.装饰器方式二
    2. def lunch(fuc):
    3. def inner():
    4. print("water hand") #在执行eat()函数前需要增加的动作
    5. fuc() #这里是lunch函数的形参,将以eat函数名作为形参,这里就是执行eat()函数一样。
    6. print("su kou") #在执行eat()函数前需要增加的动作
    7. return inner
    8. @lunch # 这里相当于eat = lunch(eat),由于lunch(eat)返回inner函数名,相当于eat()执行,就换成inner()执行一样。
    9. def eat():
    10. print("eat somethings")
    11. #执行eat()函数体,相当于调用lunch的函数,把eat函数名作为lunch函数的形参fuc传入,在不改变eat函数本身的代码,增加了一些功能
    12. eat() #执行eat()
    13. 总结:
    14. 上面两种方法,都是可以,但是看自己的需求

    二。扩展

    1. def lunch(fuc):
    2. def inner(name, number): #使用装饰器后,执行eat函数相当于执行inner函数,那这里也要有两个形参
    3. print("water hand")
    4. fuc(name, number) #在执行inner函数时,这个是调用目标eat函数,由于下面eat函数定义有两个实参,因此这里也要有对应的形参,并且数量要一样
    5. print("su kou")
    6. return inner
    7. @lunch
    8. def eat(name, num): #这里函数有实参
    9. print("吃{}水果,吃了{}个".format(name, num))
    10. #如果eat有定义实参,而装饰器没有定义形参,就会报错类似这样,# TypeError: inner() takes 0 positional arguments but 2 were given
    11. eat("apple",5)
    12. 执行结果:
    13. water hand
    14. 吃apple水果,吃了5
    15. su kou

    三,扩展三

    1. 1.如果这个food装饰器要被多个函数调用,并且是同一个功能,并且多个函数的实参是不一样的,因此就需要使用*args,来接收实参。这样不管调用这个装饰器的函数,实参多少个都可以匹配,
    2. def food(fnc):
    3. def inner(*args): #多个形参
    4. print("water hand")
    5. fnc(*args) #多个形参
    6. print("su kou")
    7. return inner
    8. @food
    9. def drink(name, num, money): #三个实参
    10. print("喝了{}酒,喝了{}瓶,一共花了{}块钱。".format(name, num, money))
    11. drink("葡萄", 10, 8888)
    12. @food
    13. def eat(name, num): #两个实参
    14. print("吃{}水果,吃了{}个".format(name, num))
    15. eat("榴莲",3)
    16. #执行结果
    17. water hand
    18. 喝了葡萄酒,喝了10瓶,一共花了8888块钱。
    19. su kou
    20. water hand
    21. 吃榴莲水果,吃了3
    22. su kou

    四。扩展四

    1. 1:下面的*args, **kwargs,这里不管位置形参,还是关键字形参都包含了,表示0个,或者多个形参匹配
    2. 注意要点:
    3. *args, **kwargs前面的 * 或者 ** ,表示把args元组和kwargs字典打散成位置参数 ,以及关键字参数传递进去,并不是说args看成一个元组作为参数传递进去。
    4. def food(fnc):
    5. def inner(*args, **kwargs):
    6. print("water hand")
    7. fnc(*args, **kwargs)
    8. print("su kou")
    9. return inner
    10. @food
    11. def drink(name, num, money):
    12. print("喝了{}酒,喝了{}瓶,一共花了{}块钱?".format(name, num, money))
    13. drink("葡萄", 10, 8888) #上面*args, **kwargs,表示匹配0个或者多个位置形参,关键字形参,所以你这里没有定义关键字实参,也是对的
    14. drink("葡萄", 10, money=8888) #定义关键字实参,
    15. @food
    16. def eat(name, num):
    17. print("吃{}水果,吃了{}个".format(name, num))
    18. eat("榴莲",3)

  • 相关阅读:
    使用CUDA计算GPU的理论显存带宽
    java104-字符串equals,charAt,endwith,startwith方法
    基于python的django的运动员成绩分析预测系统-km算法
    zookeeper整理:paxos算法学习
    真无线蓝牙耳机什么牌子好?盘点五款质量好的蓝牙耳机
    【第18章】MyBatis-Plus主键生成策略
    Spring框架技术的核心与设计思想
    134. 加油站
    [自然语言处理] 基于pycorrector实现文本纠错
    J9数字论:以太坊合并?以太坊合并又会带来哪些影响?
  • 原文地址:https://blog.csdn.net/fengge55/article/details/132944051