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

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

 

  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. CVE-2020-1947 Sharding-UI的反序列化复现及分析

    CVE-2020-1947 复现及分析 0x01 影响 Apache ShardingSphere < =4.0.0 0x02 环境搭建 incubator-shardingsphere 的ui ...

  2. 基于VR三维全景的虚拟展馆展览实现

    VR三维全景虚拟现实技术的应用,能够通过全方位互动式来还原真实场景,令人产生一种身临其境的感觉,由于三维全景虚拟现实技术具有一定应用优势,其在企业与院校展示.建筑规划展示.酒店宾馆展示等方面都逐步得到 ...

  3. leetcode面试题42. 连续子数组的最大和

      总结一道leetcode上的高频题,反反复复遇到了好多次,特别适合作为一道动态规划入门题,本文将详细的从读题开始,介绍解题思路. 题目描述示例动态规划分析代码结果 题目   面试题42. 连续子数 ...

  4. Head First设计模式——蝇量和解释器模式

    蝇量 蝇量模式:如果让某个类的一个实例能用来提供许多“虚拟实例”,就使用蝇量模式. 在一个设计房子的平台中,周围要加上一些树,树有一个坐标XY坐标位置,而且可以根据树的年龄动态将自己绘制出来.如果我们 ...

  5. 通过实现简单聊天室了解websocket的基础使用

    websocket基础使用 用到的依赖包 websocket的依赖 <dependency> <groupId>javax.websocket</groupId> ...

  6. 简单的scrapy命令和中间件

    创建爬虫 scrapy genspider 名字 xxx.com 运行爬虫 运行名为usnews的爬虫scrapy crawl usnews​运行爬虫文件scrapy runspider quote_ ...

  7. JVM进阶:JVM的监控利器

    每次聊起性能测试,最后的终极话题就是怎么做优化.其实在Java的复杂项目中都会有内存不足问题.内存泄露问题.线程死锁问题.CPU问题.这些问题在小压力的情况下有可能并不明显,很容易被忽视.但是真正到了 ...

  8. ajax3

    json json:JavaScript对象表示方法(JavaScript object notation) json:是存储和交换文本信息的语法,类似与xml.他使用键值对的方式来组织,易于人们阅读 ...

  9. Spring Data JPA 自定义对象接收查询结果集

    Spring Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和 ...

  10. HTTPS加密传输过程

    HTTPS加密传输过程 HTTPS全称Hyper Text Transfer Protocol over SecureSocket Layer,是以安全为目标的HTTP通道,在HTTP的基础上通过传输 ...