Python装饰器

函数调用加括号和不加括号的区别

  • 不带括号的函数。调用的结果是返回一个函数对象,不需要等待该函数执行完成
  • 带括号的函数,调用的结果是返回一个值,返回return的值,如果没有return则返回一个None。必须要等待函数执行完成
    def foo():
      print("ffffff")
      return "aaa"
    #不带括号的函数。调用的结果是返回一个函数对象,不需要等待该函数执行完成
    print(foo)
    #带括号的函数,调用的结果是返回一个值,返回return的值,如果没有return则返回一个None。必须要等待函数执行完成
    print(foo())

装饰器

装饰器定义

  • 装饰器是Python的一种语法糖,本质是一个可调用的对象,其参数是一个被装饰的函数。装饰器可能会处理被装饰的函数并返回,或者将其替换成另一个函数或对象
  • 语法糖是什么呢?
    语法糖指的是计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用;可以使用这种语法增加程序的可读性,从而减少程序代码出错的可能。

装饰器条件:

  • 装饰器本质上是个可调用的函数,它的参数是一个函数对象(被装饰的函数)
  • 装饰器函数的定义写在被装饰的函数之前
  • 怎么使用装饰器呢?在被装饰的函数前一行写@装饰器函数名

装饰器例子

  • 1、写一个简单的例子,没有返回值,只打印一句“这是一个函数**”
  • 2、增加需求,记录下函数的执行日志,在代码中添加日志代码
  • 3、重新定义一个函数:专门处理日志,日志处理完之后再执行真正的业务代码
#未添加装饰器
def foo():
    print("this is a func, foo")  #执行foo函数体
    #print("foo is running")
#传入函数对象func
def log(func):
    print("{} is running".format(func))  #打印日志
    func() #调用func()

log(foo)

#加入装饰器实现上述功能
def log2(func):
    print("{} is running".format(func))
    return func

@log2   #装饰器-----#先执行装饰器函数(打印日志),返回func函数对象;
def foo2(): #调用函数
    print("this is a func, foo2")

foo2()

图片说明

装饰器何时执行

  • 装饰器在被装饰的函数定义之后立即执行(即Python加载模块的时候)
#定义一个列表
registry = []

#定义一个函数,传入一个参数(函数对象)
def register(func):
    print("register is ",func)
    #把函数对象存入regitry列表中
    registry.append(func)
    #返回一个函数对象
    return func

@register
def f1():
    print("f1")

@register
def f2():
    print("f2")

def f3():
    print("f3")

if __name__ == '__main__':
    print("running main()")
    print("regitry->",registry)
    f1()
    f2()
    f3()

打印结果:
图片说明

装饰器的两种用法

  • 原封不动返回被装饰函数(如上面例子所示)
  • 把被装饰函数替换成新函数
    • 大多数装饰器,通常内部会定义一个闭包结构的函数,将其返回替换被装饰函数,用于不修改原函数的基础上增加额外的功能

闭包函数

一般是在装饰器中使用的

闭包函数满足三个条件:

  • 在一个外函数中定义了一个内函数,
  • 内函数里运用了外函数的临时变量,
  • 并且外函数的返回值是内函数的引用,这样就构成了一个闭包
    #闭包函数——outer是外部函数,a和b都是外部函数的临时变量
    def outer(a):
      b=10
      #inner是内函数
      def inner():
          #在inner中用到了外函数的临时变量
          print(a+b)
      #outer外函数得到返回值是内函数的引用
      return inner

把被装饰函数修饰成一个新函数

def log2(func):
    def log(a,b):
        print("{} is running".format(func))
        func(a,b)
    return log

@log2
def foo2(a,b):
    print("this is a func, foo2")
    print(a+b)

foo2(1,2)
全部评论

相关推荐

04-16 10:27
已编辑
美团_Saas_后端开发
今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,拿到美团offer那会感觉自己天都亮了。没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
03-10 10:57
已编辑
门头沟学院 推荐算法
夜夜还好:我们学校说为了学生就业,更新了课程,我今天大二,上学期在学jsp,html,这学期上来工程实践,要求用springboot+vue,说什么这些技术要我们提前自己准备,要不你把学费还我吧,我给b站充个会员,人家教的比你多
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务