zoukankan      html  css  js  c++  java
  • 内置函数 lambda sorted filter map 递归

    一 lambda 匿名函数

      为了解决一些简单的需求而设计的一句话函数

    # 计算 n 的 n次方
    
    def func(n):
        return n**n
    print(func(10))
    
    
    
    f = lambda n:n**n
    print(f(10))

    lambda 表示的是 匿名函数,不需要用 def 声明,一句话就可以声明出一个函数 

    语法:

      l函数名 = lambda 参数:返回值

    注意:

      1.返回值可以是一个,也可以是多个,多个 的时候用  逗号  隔开   在 元祖 () 里边

      2.lambda 不管多复杂 只能写 一行 , 执行完毕 返回数据

      3.lambda 和正常 函数一样 ,返回值 可以 是 任意 数据类型 

          匿名函数并不是说一定没有名字. 这里前面的变量就是一个函数名. 说他是匿名原因是我们通
    过__name__查看的时候是没有名字的. 统一都叫lambda. 在调用的时候没有什么特别之处.像正常的函数调用即可

    二  sorted     排序函数

    语法:

      sorted(iterable,key = None,reverse=False)

          iterable :可迭代对象

          key = 排序规则(排序函数)   在  sorted 内部 会将 可迭代对象中的 每一个 元素传递给 这个函数的参数

             根据 函数运算的 结果进行 排序

          reverse; 是否是 倒序      True 倒序   False   正序

    lst = [1,5,8,9,2,6,4,3,7]
    lst1 = sorted(lst)
    print(lst)    # [1, 5, 8, 9, 2, 6, 4, 3, 7] 原列表不变
    print(lst1)   # [1, 2, 3, 4, 5, 6, 7, 8, 9] 返回的列表是经过排序的
    
    dic = {1:"a",3:"b",2:"c"}
    dic1 = sorted(dic)
    print(dic)          #  {1: 'a', 3: 'b', 2: 'c'}
    print(dic1)      #  [1, 2, 3] 如果是字典,返回经过排序的 key
    # 和 函数 组合使用
    lst = ["张曼玉","邱淑贞","朱茵","","上官寒冰"]
    def func(s):
        return len(s)
    
    print(sorted(lst,key=func))
    # ['你', '朱茵', '张曼玉', '邱淑贞', '上官寒冰']
    
    
    # 和 lambda 组合使用
    lst = ["张曼玉","邱淑贞","朱茵","","上官寒冰"]
    
    lst1 = (sorted(lst,key = lambda s:len(s)))
    print(lst1)   #  ['你', '朱茵', '张曼玉', '邱淑贞', '上官寒冰']


    lst = [{"id":1, "name":'alex', "age":18},
    {"id":2, "name":'wusir', "age":16},
    {"id":3, "name":'taibai', "age":17}]

    # 按照年龄对学生进行排序

    func = sorted(lst,key=lambda dic:dic["age"])
    print(func)
     

    三 filter()  筛选函数

    语法:

      filter(function,iterable)

        function:用来筛选的函数,在 filter 中 会自动的吧 iterable  中的 元素传递个i function,然后根据 function返回

            的 True  或者  False 来判断是否保留 此项数据

        iterable : 可迭代对象

    #筛选所有的 偶数
    lst = [1,2,3,4,5,6,7,8,9]
    l = filter(lambda x:x % 2 == 0,lst)
    print(l)         # <filter object at 0x013E7690>
    print(list(l))   #  [2, 4, 6, 8]
    
    
    lst = [{"id":1, "name":'alex', "age":18},
            {"id":2, "name":'wusir', "age":16},
            {"id":3, "name":'taibai', "age":17}]
    
    # 筛选年龄大于 16 的数据
    lst1 = filter(lambda dic:dic["age"]>16,lst)
    print(list(lst1))
    
    # [{'id': 1, 'name': 'alex', 'age': 18}, {'id': 3, 'name': 'taibai', 'age': 17}]

    四 map() 映射函数

      语法:

        map(function,iterable) 可以对 可迭代对象中的 每一个 元素 进行映射 ,分别取执行 function 

    #  计算列表中 每个元素的 平方,返回新列表
    # 1.和函数 组合 使用
    
    def func(s):
        return s**2
    
    mp = map(func ,[1,2,3,4])
    print(mp)             ##   <map object at 0x013F7710>
    print(list(mp))       ##   [1, 4, 9, 16]
    
    
    # 2.和 lambda 组合 使用
    
    print(list(map(lambda i:i**2,[1,2,3,4])))
    # [1,4,9,16]
    
    
    # 计算两个 列表中 相同 位置的数据的 和
    
    lst = [1,2,3,4,5]
    lst1 = [5,4,3,2,1]
    
    print(list(map(lambda x,y:x+y,lst,lst1)))  #  [6, 6, 6, 6, 6]

    五    reduce()  通过某个函数,累计按顺序计算列表中的值  可以 算 累加   累乘 等等吧

    python2.x 中 直接  import reduce

    python3.x  中    from functools import reduce

    from functools import reduce
    def func(x,y):
        return x + y
    
    # reduce 的使用方法
    # reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行
    ret = reduce(func,[3,4,5,6])
    print(ret)
    
    
    reduce 的作用是 先把列表中的 前两个元素取出计算一和值,然后临时保存
    接下来用这个零时保存的值 和 列表中的下一个 再计算,以此类推 
    
    # 注意 我们放进去的可迭代对象没有 更改
    from functools import reduce    #  导入reduce 模块
    
    
    #  和 lambda 组合 使用 
    
    print(reduce(lambda x,y:x*y,[1,2,3,4]))   # 24

    六 zip()  拉链函数   

    zip(*iterables) 生成一个 迭代器(迭代器本质是 生成器),它聚合了 可迭代对象的 每个元素

    返回 一个 由 元祖组成的 迭代器,其中 第 i 个元祖 包含 来自每个参数序列 或 可迭代对象的 第i个元素,

    当最短的 可迭代对象被 输出时,该 迭代器完成

    # 原理如下
    def zip(*iterables):
        # zip("ABCD","xy") ---> Ax By
        sentinel = object()
        itetators = [iter(it) for it in iterables]
        while itetators:
            result = []
            for it in itetators:
                elem = next(it,sentinel)
                if elem is sentinel:
                    return
                result.append(elem)
                yield tuple(result)
    
    f = zip([1,2,3],[4,5,6,7])
    
    print(f.__next__())     # (1,)
    print(f.__next__())     # (1, 4)
    print(f.__next__())    #  (2,)
    print(f.__next__())    #  (2, 5)

    x = [1,2,3,4]
    y = ["张曼玉","邱淑贞","张敏"]
    z = [11,22,33,44,55]

    print(list(zip(x,y,z)))
    # [(1, '张曼玉', 11), (2, '邱淑贞', 22), (3, '张敏', 33)]

    print(list(zip(*zip(x,y,z))))
    # [(1, 2, 3), ('张曼玉', '邱淑贞', '张敏'), (11, 22, 33)]
    # * 的作用是把上面生成的 迭代器 又 再次 拉链式的 组合了该 迭代器中的 元素
    lst = [1,2,3,4,5,6]
    lst1 = ["anglobay","haha","hahag","张敏","邱淑贞"]
    tu = ("**","***","****","******")
    
    b = filter(lambda x:x[0] > 2 and len(x[2]) > 4,zip(lst,lst1,tu))
    print(list(b))
    
    # [(4, '张敏', '******')]

    七  递归函数     在函数中调用函数本身,就是递归

    递归是什么

    在数学和计算机科学中,递归指由一种(或多种)简单的基本情况定义的一类对象或方法,

    并规定其他所有情况都能被还原为其基本情况。

    递归的三要素

    • 一个问题的解可以分解为几个子问题的解
    • 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
    • 一定存在终止递归的条件

    关键点

    • 写出递推公式
    • 找到终止条件
    • 将递推公式转化为代码

    递归代码要警惕堆栈溢出

    函数调用会使用栈来保存临时变量,每调用一个函数,都会将临时变量封装为栈帧压入内存栈,等函数执行完成返回时,才出栈。系统栈或者虚拟机栈空间一般都不大,如果递归求解的数据规模很大,调用层次很深,一直压入栈,就会有堆栈溢出的风险。

    如何避免堆栈溢出?

    • 在代码中限制递归调用的最大深度,当递归调用超过一定深度,比如1000之后,就不再继续往下递归了,直接返回报错。但是如果递归深度比较大,这种方法就不太适用。
    • 采取循环的方式来解决,将需要的数据在关键的调用点保存下来使用。简单的说,就是用自己的数据保存方法来代替系统递归调用产生的堆栈数据。 

    递归代码要警惕重复计算

    使用递归的时候,还会出现重复计算的问题。为避免重复计算,我们可以通过一个数据结构(比如散列表)来保存已经求解过的递归函数值 f(k),当递归调用到 f(k) 时,先看下是否已经求解过了,如果是,则直接从散列表中取值返回,不需要重复计算,这样就能避免重复计算了。

    内容小结

    • 递归是一种非常高效、简洁的编程技巧。
    • 只要是满足“递归三要素”的问题,就可以通过递归代码来解决。
    • 编写递归代码的关键点在于:写出递推公式,找出终止条件,然后再翻译成递归代码。
    • 递归代码虽然简洁高效,但是也存在很多弊端,如:堆栈溢出、重复计算、函数调用耗时多、空间复杂度高等等,在使用递归时,一定要控制好这些副作用。
    def func():
        print("我是func")
        func()
    fucn()
    
    # 在python 中,官方解释 递归最大深度1000,但是永远不会跑到1000
    # 我实测 998
    
    # 怎么测的 呢?? 其实很简单,就是利用累加 
    
    def func(n):
        print(n)
        n += 1
        func(n)
    func(1)

    递归的应用:

      我们可以使用递归来遍历各种树形 结构,比如我们的文件夹系统

    # 引入os 模块
    import os
    
    def func(filepath,n):
        files = os.listdir(filepath) # 获取到当前文件夹的所有文件
        for fi in files:             # 遍历文件夹中的 内容,这里获取到的是本层文件名
            fi_d = os.path.join(filepath,fi)  # 加入文件夹,获取到文件夹 + 文件
            if os.path.isdir(fi_d):     # 如果该路径下的是文件夹
                print("	"*n,fi)      #  打印出文件名
                func(fi_d,n +1)      # 继续进行相同的 操作
            else:
                print("	" * n, fi)   # 递归出口,最终在这里隐含着 return 
    # 递归 遍历 d盘目录下 所有文件
    func("d:/learn-py",0)

    八  二分查找  

      每次查找能够排除掉一半 的数据,查找的效率 非常高,但是局限性比较大,必须是有序序列才可以用二分法

    要求: 查找的序列 必须是 有序序列

    #  二分查找 ----  非递归算法
    lst = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100,101,111,222,333]
    num = int(input("输入你要查找的数字:"))
    left = 0
    right = len(lst) - 1
    count = 1
    while left <= right:
    middle = (left + right) // 2
    if num < lst[middle]:
    right = middle - 1
    elif num > lst[middle]:
    left = middle + 1
    else:
    print(count)
    print(middle)
    break
    count += 1

    else:
    print("不存在")
     
    # 普通 递归版本 二分法
    # 利用 索引切片,切了列表,不符合的 切掉
    # 当 列表 切完了之后,就可以判断了
    # 很难计算 位置
    lst = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100,101,111,222,333]
    
    num = int(input("输入你要查找的数字:"))
    def func(n,lst):
        left = 0
        right = len(lst) - 1
        if lst != []:
            middle = (left + right) // 2
            if num > lst[middle]:
                func(n,lst[middle + 1:])
            elif num < lst[middle]:
                func(n,lst[:middle])
            else:
                print("找到了")
                return None
        else:
            print("没找到")
            return None
    print(func(num,lst))
    # 判断 num 是不是在 列表中,可以返回 num 所在的 位置
    # 用 递归,要找到设么是 可变的,什么是不可变的 
    # 列表不动
    lst = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77,88,99,100,101,111,222,333]
    
    num = int(input("输入你要查找的数:"))
    def func(n,lst,left,right):
        if left <= right:
            middle = (left + right) // 2
            if n > lst[middle]:
                left = middle + 1
                return func(n,lst,left,right)
            elif n < lst[middle]:
                right = middle - 1
                return func(n,lst,left,right)
            else:
                print("找到了")
                return middle
        else:
            print("找不到")
            return -1
    ret = func(num,lst,0,len(lst) - 1)
    print(ret)
    # 还有一种查找方法
    # 堪称最快之 查找方法 ,此方法 不需要 列表是 有序的
    
    lst = [1,2,55,66,88,3,44,6,5,7,8,111,222,333]
    new_lst = []
    for i in range(334):
        new_lst.append(i)
    for el in lst:
        new_lst[el] = 1
    num = int(input("输入你要查找的数字:"))
    if new_lst[num] == 0:
        print("不存在")
    else:
        print("存在")
  • 相关阅读:
    局部变量和全局变量
    Javascript高级编程学习笔记(26)—— 函数表达式(4)私有变量
    Javascript高级编程学习笔记(25)—— 函数表达式(3)模仿块级作用域
    Javascript高级编程学习笔记(24)—— 函数表达式(2)闭包
    Javascript高级编程学习笔记(23)—— 函数表达式(1)递归
    Javascript高级编程学习笔记(22)—— 对象继承
    Javascript高级编程学习笔记(21)—— 对象原型
    Javascript高级编程学习笔记(20)—— 创建对象
    Javascript高级编程学习笔记(19)—— 对象属性
    Javascript高级编程学习笔记(18)—— 引用类型(7)单体内置对象
  • 原文地址:https://www.cnblogs.com/wenqi2121/p/10268644.html
Copyright © 2011-2022 走看看