zoukankan      html  css  js  c++  java
  • 匿名函数python内置高阶函数以及递归

    匿名函数

    python定义一个函数通常使用def关键词,后面跟函数名,然后是注释、代码块等。

    def func():
        '''注释'''
        print('from func')
    

    这样就在全局命名空间定义了一个叫func的函数,func表示函数体的内存地址,因为func指向函数体内存地址,所以可以通过func来调用函数。

    那么匿名函数呢?从名字就可看出,匿名。想想就有点像以前小时候的佚名一样,带点说不清楚的神秘色彩,现在想来之所以感觉神秘可能是因为那时候不认识‘’佚‘’这个字。。。

    强调:
        匿名函数的定义就相当于只产生一个变量在值,而没有绑定任何名字,
        所以会在定义完之后就被回收,无法重复使用,只能在定义时使用一次
    应用:当某一个功能仅使用一次就没有再重复使用的必要了,就应该定义成匿名函数
    

    言归正传,匿名和佚名一样没有名字或者不需要知道名字,对就是这么酷。

    定义一个匿名函数使用lambda关键词,和def比较的话会发现其实定义逻辑很像。

    lambda x: x**2
    

    定义的匿名函数的意思是参数为x,返回x的平方,返回?怎么没看到return?因为lambd引号后面的值默认返回,所以没必要加return了,但是我一定要加呢?就是这么不讲道理。那么解释器只好报错了,因为你不认同我的语法,那我也没必要惯着你了。就是这么拽。

    匿名函数的使用场景通常为使用一次就结束了,不会频繁的使用。而且匿名函数通常和python里面自带的高阶函数结合使用,在某些应用场景下会达到事倍功半的效果哦。

    高阶函数

    map

    map的意思是地图的意思,由此引申出映射表示一一对应。

    翻译过来的意思是:创建一个迭代器,使用每个迭代的参数计算函数。 当最短的可迭代用尽时停止。

    map函数有两个参数,第一个为某种规则的函数,第二个位多个可迭代对象。

    def func(x):
        return x * 2
    lis = [1, 2, 3, 4, 5, 6]
    print(type(map(func, lis)))
    print(list(map(func, lis)))
    

    map函数把可迭代对象中的元素自动传给func,通过func的加工,得到一个生成器对象,通过list函数转化为一个列表。

    当然,map函数可以接收多个可迭代对象,比如

    def func(x, y):
        return x + y
    lis1 = [1,2,3,4,5,6]
    lis2 = [2,3,4,5,6,7,8,9,10,11]
    print(list(map(func, lis1,lis2)))
    # 结果为[3, 5, 7, 9, 11, 13]
    

    map函数会把后面迭代器对象中的元素迭代出来经过func加工,当最短的可迭代用尽是停止,所以只进行到6+7就结束了。

    reduce

    reduce是减少、合并的意思,会把可迭代对象中的元素经过函数的加工进而产生新的结果。

    翻译过来就是:从左到右累加两个参数的函数到序列的项目,以便将序列减少为单个值。例如,reduce(lambda x,y:x + y,[1,2,3] ,4,5]计算(((((1 + 2)+3)+4)+5)。如果存在初始值,则将其放置在计算中序列的项之前,并在序列为空时用作默认值。

    reduce函数有三个参数,函数和序列都是必须参数,初始值为可选参数。

    应用:比如求1-100的和

    from functools import reduce
    def func(x, y):
        return x+y
    print(reduce(func, [i for i in range(1,101)]))
    # 结果为 5050
    

    filter

    filter的意思为过滤,通过函数的返回值对序列进行过滤。

    翻译过来:返回一个迭代器,产生函数(item)为真的迭代项。 如果函数为None,则返回结果为真的项。

    def func(x):
        return x.isdigit()
    lis = ['12', 'ad', '34', 'bc', '46']
    print(list(filter(func, lis)))
    # 结果为 ['12', '34', '46']
    

    filter过滤结果为真的值放进迭代器中。

    高阶函数和匿名函数

    map和匿名函数

    在之前map函数中的func参数都是定义了一个有名参数,然后用函数名传入map函数的,有了匿名函数就不用这么麻烦了。

    lis = [1, 2, 3, 4, 5, 6]
    print(list(map(lambda x: x*2, lis)))
    # 结果为 [2, 4, 6, 8, 10, 12]
    

    reduce和匿名函数

    print(reduce(lambda x, y: x + y, [i for i in range(101)], 100))
    # 输出结果为 5050
    

    filter和匿名函数

    sala = {
         'MAC': 30000,
         'iPhone': 9000,
         'lenovo': 10000,
         'xiaomi': 3000
    }
    print(list(filter(lambda x: sala[x] > 5000, sala)))
    # 输出结果为 [‘iPhone', 'lenovo']
    

    匿名函数的使用场景较为单一,一次性使用,随用随时定义。在某些场景下和高阶函数结合会提升效率,同时使代码更加简洁。

    递归

    一 递归调用的定义

    递归调用时函数嵌套调用的一种特殊形式,函数在调用时,直接或间接地调用了自身,就是递归调用。

    # 直接调用自身
    def f1():
        print('from f1')
        f1()
    f1()
    
    # 间接调用自身
    def f1():
        print('from f1')
        f2()
    
    
    def f2():
        print('from f1')
        f1()
    f2()
    
    # 调用函数会产生局部的名称空间,占用内存,因为上述这种调用会无限调用自身,python解释器的内存管理机制为了防止无限占用内存,对函数的递归调用做了层级限制,可以通过代码修改最大层级限制。
    import sys
    sys.setrecursionlimit(100000)
    

    二 递归调用的两个阶段

    递归调用包含两个明确的阶段:回溯,递推

    • 回溯就是从外向里一层一层递归调用下去,回溯阶段必须要有一个明确的结束条件(不然会成为死循环),每进入下一次递归时,问题的规模都应该有所减少。

    • 递推就是从里向外一层层结束递归。

    • 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈实现的,每当进入一个函数调用,在栈下面会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以递归调用次数过多,会导致栈溢出)

    三 二分法

    从一个排序的数字列表中找到指定的数字,使用遍历的效率太低,使用二分法可以极大地缩小问题规模。

    1. 实现in的效果

      nums = [1,5,12,23,34,46,59,99,443]
      
      def fucn(num, nums):
          if len(nums) == 0:
              return
          mid_index = len(nums) // 2
          if num > nums[mid_index]:
              nums = nums[mid_index+1:]
              fucn(num, nums)
      
          elif num < nums[mid_index]:
              nums = nums[:mid_index]
              fucn(num,nums)
          else:
              print('not exis')
      
    2. 实现index的效果

      nums = [1, 13, 15, 23, 27, 31, 33, 57, 73, 81, 93, 94, 97, 101]  # 从小到大排列的数字列表
      def binary_search(find_num,nums):
          print(nums)
          if len(nums) == 0:
              print('not exists')
              return
      
          # 功能
          mid_index = len(nums) // 2
          if find_num > nums[mid_index]:
              # in the right
              nums=nums[mid_index+1:]
              # 重新运行功能,传入新列表
              binary_search(find_num,nums)
          elif find_num < nums[mid_index]:
              # in the left
              nums=nums[:mid_index]
              # 重新运行功能,传入新列表
              binary_search(find_num,nums)
          else:
              print('find it')
              
      binary_search(95,nums)
      
  • 相关阅读:
    Python数据分析与机器学习-Matplot_2
    Python数据分析与机器学习-Matplot_1
    1008. 数组元素循环右移问题 (20)
    Latex小技巧
    执行PowerShell脚本的时候出现"在此系 统上禁止运行脚本"错误
    Linux使用MentoHust联网线上校园网, 回到普通有线网络却连不上?
    Re:uxul
    Linux下nautilus的右键快捷菜单项设置
    从入门到入狱——搭讪技巧
    Latex命令
  • 原文地址:https://www.cnblogs.com/zuanzuan/p/9768972.html
Copyright © 2011-2022 走看看