本文介绍:高阶函数,嵌套函数,以及由前面两个组成的装饰器

一、高阶函数:以下两种情况都是高阶函数

 

  1、将函数名当成参数传递给另外一个函数(作用:不修改被传递函数源代码就可以添加新功能):

  import time
  def a():
  time.sleep(1)
  print("This is A funciton...")
  # b函数相当于给a函数附加了一个计算时间的功能,但未修改a的源代码
  def b(func):
  print(func) # 打印func的内存地址
  start_time = time.time()
  func() # 调用a()
  end_time = time.time()
  print("a函数运行时间为:%s秒" % (end_time - start_time))
  b(a) # 将a函数当成一个变量传递给b

  2、将函数名当成返回值返回给另外一个函数(作用:不修改被传递函数调用方式就可以添加新功能):

  import time

  def a1():

  time.sleep(1)

      print("This is A1 funciton...")

  # b1函数相当于给a1函数附加了一个计算时间的功能,但未修改a的源代码,也未修改a1的调用方式

  def b1(func):
  start_time = time.time()
  func() # 调用a()
  end_time = time.time()
  print("a函数运行时间为:%s秒" % (end_time - start_time))
  return func
  a1 = b1(a1) # 将a1函数当成一个变量传递给b1
  a1() # 调用未改变a1的调用方式,依然是a1()调用,只不过此时的a1已经通过b1装饰过了。   
二、嵌套函数:在函数内部定义一个新的函数,注意:函数内部根据就近原则一层层往外寻找变量
    x = 0
    def grandpa():
      x = 1
      def dad():
    x = 2
        def son():           x = 3
              print(x)
    son()
    dad()
    grandpa()


三、装饰器:


  1、定义:在不修改函数代码和调用方式的前提下对该函数实现新功能的编程范式,形式上是利用高阶和嵌套函数的特性,高阶函数 + 嵌套函数 = 装饰器,
       所以装饰器本质上是一个未其他函数添加新功能的函数,而且不破坏原有代码。
  2、原则:
      a、不能修改被装饰函数的代码,此项可以防止修改以后对原来的程序逻辑造成影响
      b、不能修改被修饰函数的调用方式,比如原来是test()这样调用的,不能改成test(参数1)或者改名成test2()调用,这也是为了让原来的旧代码逻辑不会出现问题导致程序运行失败。
      c、综上所述,也就是说被装饰的函数感觉不到装饰器的存在,装饰器是透明的。   3、如何实现装饰器?
      a、函数也是一个变量,函数名是变量名,函数执行体就是具体的函数值,所以将函数名赋值给别的函数,在别的函数内部就可以直接使用该函数。
      b、单层装饰器:将函数名当成变量传递给另外一个函数,以达到装饰添加新功能的目的。
        def timer(func):
        def deco(*args,**kwargs): #这是一个嵌套函数,将*args和**kwargs可以允许外界传入任意个数的位置和关键词参数进来
        start_time = time.time()
        func(*args,**kwargs)
        stop_time = time.time()
        print("the func run time is %s" % (stop_time - start_time))         return deco         @timer #@timer标签就相当于这句话 test1 = time(test1) 将test1函数变量名传给装饰器
        def test1():
        time.sleep(1)
        print("This is test1")         @timer # test2 = time(test2)
        def test2(name,age):
        time.sleep(2)
        print("This is %s age:%d"%(name,age))         test1()
        test2("test2",23)   c、通过嵌套函数两层装饰器,可以让装饰器传递参数         def outside(arg_type):
        def inside(func):
        def deco(*args, **kwargs):
        return_value = ""
        if arg_type == "1":
        print("加载功能1")
        return_value = func(*args, **kwargs)
        print("加载功能2")
        elif arg_type == "2":
        print("加载功能3")
        return_value = func(*args, **kwargs)
        print("加载功能4")
        else:
        return_value = func(*args, **kwargs)
        print("加载功能5")
        return return_value # 这个返回值可以让被装饰的func函数的返回值传到外面
        return deco
        return inside         @outside(arg_type="1") # 在打标签装饰的同时,还可以传递参数给外层outside
        def test1():
          print("This is test1")
      return "test1"         @outside(arg_type="2")
        def test2():
        print("This is test2")
        return "test2"         @outside(arg_type="3")
        def test3(1,2):
        print("This is test3")
        return "test3"         # test1,test2和test3的的调用方式和其内部代码都未改变,但是通过装饰器却添加了新功能
        print(test1())
        print(test2())
        print(test3())

Python学习笔记:函数详解(下)的更多相关文章

  1. python基础之函数详解

    Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ...

  2. Python内置函数详解

    置顶   内置函数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii https://docs.pyth ...

  3. python pandas字符串函数详解(转)

     pandas字符串函数详解(转)——原文连接见文章末尾 在使用pandas框架的DataFrame的过程中,如果需要处理一些字符串的特性,例如判断某列是否包含一些关键字,某列的字符长度是否小于3等等 ...

  4. Angular6 学习笔记——组件详解之模板语法

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  5. Angular6 学习笔记——路由详解

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  6. Angular6 学习笔记——组件详解之组件通讯

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  7. JavaScript学习笔记-实例详解-类(二)

    实例详解-类(二)   //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...

  8. JavaScript学习笔记-实例详解-类(一)

    实例详解-类(一): //每个javascript函数(除了bind())都自动拥有一个prototype对象// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性const ...

  9. Python学习笔记—函数

    函数 我们知道圆的面积计算公式为: S = πr2 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同大小的圆的面积: r1 = 12.34 r2 = 9.08 r3 = 73 ...

  10. Android学习笔记-Dialog详解

    1.对话框的使用 1.1AlertDialog的显示 简单对话框以及监听的设置:重点掌握三个按钮(也就是三上单词): PositiveButton(确认按钮);NeutralButton(忽略按钮) ...

随机推荐

  1. 题解-[HNOI2001]遥控赛车比赛

    题解-[HNOI2001]遥控赛车比赛 前置知识:记忆化搜索.\(\texttt{Bfs}\). 参考资料 https://www.luogu.com.cn/blog/CYJian/solution- ...

  2. 移动webApp必备技能一、WebApp 里Meta标签大全,webappmeta标签大全

    1.先说说mate标签里的viewport: viewport即可视区域,对于桌面浏览器而言,viewport指的就是除去所有工具栏.状态栏.滚动条等等之后用于看网页的区域.对于传统WEB页面来说,9 ...

  3. 20 本地SQL查询

    Spring Data JPA同样也支持sql语句的查询 //nativeQuery : 使用本地sql的方式查询 @Query(value="select * from customer& ...

  4. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

    一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...

  5. web安全测试--环境搭建

    本博客主要作为作者的学习笔记,请勿装载. 作为一个安全测试的入门选手,一切操作在虚拟机中进行是最保险的. 第一先下载自己喜欢的虚拟机,我的笔记本用的VirtualBox(下载地址:https://ww ...

  6. C# .Net Core 3.1 中关于Process.Start 启动Url链接的问题

    WPF 项目迁移到.Net Core中时居然出了一堆问题...(很无语) 今天在使用的时候居然发现Process.Start居然打不开Url链接了? 报 找不到指定文件 的异常?! 一.bug重现 首 ...

  7. 题解 UVA12186 【工人的请愿书 Another Crisis】

    俺太难了 记录一下我调了一个小时的错误 多测不清空 多测清空只清空了\(vector\) 多测全清空了,但是忘了清空\(vector[0]\) \(priority\)_ \(queue\)把\(gr ...

  8. 微信小程序开发中的http请求总结

    在微信小程序进行网络通信,只能和指定的域名进行通信,微信小程序包括四种类型的网络请求. 普通HTTPS请求(wx.request) 上传文件(wx.uploadFile) 下载文件(wx.downlo ...

  9. XML的概述,.Dom4解析和SAX解析

    1.什么是XML XML 指可扩展标记语言(EXtensible Markup Language) html(hyper text markup langauge) XML 是一种标记语言,很类似 H ...

  10. [Dynamic Programming]动态规划之背包问题

    动态规划之背包问题 例题 现有4样物品n = ['a', 'b', 'c', 'd'],重量分别为w = [2, 4, 5, 3],价值分别为v = [5, 4, 6, 2].背包最大承重c = 9. ...