zoukankan      html  css  js  c++  java
  • python递归-三元表达式-列表生成式-字典生成式-匿名函数-部分内置函数-04

    递归

    递归: # 函数在调用阶段直接或间接地又调用了自身 

    应用场景: # 将列表中的数字依次打印出来(循环的层数是你必须要考虑的点)   -->  l = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, [11, [12, [13, ]]]]]]]]]]]]] 

    # 循环的写法, 列表嵌套越多层越麻烦
    for i in l:  # 推导思路
        if type(i) is int:
            print(i)
        else:
            for item in i:
                if type(item) is int:
                    print(item)
                else:
                    for j in item:
                        if type(item) is int:
                            print(item)
                        else:
                            ...  # 函数体的顶用方式(还有一是前面提到过的pass,推荐还是使用 pass来顶替,比较明目)
                            # 下方嵌套多级循环,往里面取到更下一层列表中的元素
    
    
    # 递归的写法,代码体简短,不需要考虑循环次数
    def get_num(l):
        for i in l:
            if type(i) is int:
                print(i, end=' - ')
            else:
                get_num(i)
    
    
    get_num(l)
    # 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 
    解决方案(循环取与递归取的对比)

    递归的优点: 递归函数不要考虑循环的次数 只需要把握结束的条件即可 

    递归的两个阶段

      回溯:# 从外向里一层一层递归调用下去,回溯阶段必须要有一个明确的结束条件,每进入下一次递归时,问题的规模都应该有所减少(单纯地重复调用自身是毫无意义的)  

      递推: # 递推就是从里向外一层一层结束递归 

    递归案例:

    def index():
        print('from index')
        login()
    
    def login():
        print('from login')
        index()
    
    login()
    # ..........................此处省略一大堆报错............................................
    # File "E:/PyCharm 2019.1.3/ProjectFile/day010/day012/01 函数递归.py", line 120, in index
    #     print('from index')
    # RecursionError: maximum recursion depth exceeded while calling a Python object  # 意思是超出了最大递归限数

    从上述案例中可得知 python解释限制了递归的深度(不然就是无限循环下去,直到你的内存溢出,然后。。。emmm)

    那么下面我们就来测试一下 python解释器中的递归深度

    # 1.暴力测试 --> 997、998左右
    count = 0
    def index():
        global count
        print(count)
        count += 1
        index()
    
    
    index()
    # .....此处省略报错
    # 997  # 最后打印的数字是 997,意味着 python解释器的递归深度约为997
    
    # 2.getrecursionlimit
    import sys
    print(sys.getrecursionlimit())  # 不是很精确
    # 1000

    那么如何修改默认的递归深度呢?

    # 修改递归深度限制
    import sys
    sys.setrecursionlimit(1100)

    应用场景2(有序列表中元素的二分法查找)

    # 抛去 成员运算 in 可以直接返回元素在不在列表中,下面探究递归运用
    # 歧义命名 l_find,
    #   这里的 l_find 代表“列表查找”,可能会与下面的往右分割列表查找,往左分割存在歧义
    #   所以命名规范里的见名知意也要注意,避免引起歧义
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    # 默认约定输入的必须是数字(乱输的咱就不考虑在内了)
    find_num = int(input("请输入您要查找的数字>>>:").strip())
    
    
    def l_find(find_num, l):
        # print(l) # 可以打印中间步骤
        mid_index = len(l) // 2
        if not l:  # 如果是空列表了,说明该元素不在列表里
            return False
        # 如果目标元素大于中间元素,那就说明元素在右边
        if find_num > l[mid_index]:
            # 利用列表的切片知识,将列表切割成一个新的列表,用于递归继续查找
            tmp_l = l[mid_index + 1:]
            res = l_find(find_num, tmp_l)
        elif find_num == l[mid_index]:
            # print("get it", find_num)
            return True
        # 如果目标元素小于中间元素,那就说明元素在左边
        else:
            tmp_l = l[0:mid_index]
            res = l_find(find_num, tmp_l)
        return res
    
    
    is_exits = l_find(find_num, l)
    if is_exits:
        print(f"您所要查找的数字{find_num} 在列表l 中。")
    else:
        print(f"您所要查找的数字{find_num} 不在列表l 中。")
    # 请输入您要查找的数字>>>:9
    # 您所要查找的数字9 在列表l 中。

    算法: 解决问题的高效率的方法(不仅仅局限于数学运算) 

    三元表达式

    先来看这样一段代码

    # 比较两个数的大小
    def my_max(x,y):
        if x > y:
            return x
        else:
            return y

    三元表达式实现: res = x if x > y else y ,短短一行就实现了上面函数的功能

    三元表达式固定格式: 值1 if 条件 else 值2 ,如果条件成立,返回 值1 ,不成立返回 值2 

    常见应用场景:( 在编程的时候请尽量避免使用三元表达式嵌套,想要知道结果要去推算,不够直接 )

    is_free = input("请输入是否免费(y/n)>>>:")
    is_free = '免费' if is_free == 'y' else '收费'
    print(is_free)
    # 请输入是否免费(y/n)>>>:n
    # 收费

    列表生成式(知识点理解可能有误)

    需求: 给列表中的除了 macbook的名字都加个马甲 new_ --> new_tank ,

    staff = ['tank', 'nick', 'oscar', 'sean', 'macbook']
    # 给列表中的除了 macbook的名字都加个马甲 new_ --> new_tank
    # for循环实现
    staff = ['tank', 'nick', 'oscar', 'sean', 'macbook']
    staff2 = []
    for people in staff:
        if people != 'macbook':
            staff2.append("new_%s" %people)
        else:
            staff2.append(people)
    print(staff2)
    # ['new_tank', 'new_nick', 'new_oscar', 'new_sean', 'macbook']
    
    
    # 列表表达式实现
    staff = ['tank', 'nick', 'oscar', 'sean', 'macbook']
    print(['new_%s' %name for name in staff if name != "macbook"])  # macbook 不满足条件,所以被滤过了
    # ['new_tank', 'new_nick', 'new_oscar', 'new_sean']
    # print(['new_' + name for name in staff if name != "macbook"])
    # 跟上条语句一样的执行效果,不过python不推荐字符串直接相加的拼接方式,它的效率十分的低!应尽量避免使用!
    
    
    # 三元表达式结合列表表达式实现
    staff = ['tank', 'nick', 'oscar', 'sean', 'macbook']
    print([f'new_{name}' if name != 'macbook' else name for name in staff])
    # ['new_tank', 'new_nick', 'new_oscar', 'new_sean', 'macbook']
    代码实现

      可以看到,列表生成式只用了一行就实现了。

    列表生成式原理(if后面可以不写)

    '''
    先for循环依次取出列表里面的元素
        然后交由 if 判断, 条件成立才会把元素交给for 前面的代码
        如果当前条件不成立, 当前元素直接舍弃
            不支持再加else 的情况(for 有 else , if 也有 else  会造成冲突)
    '''

    字典生成式

    需求:将 l1 = ['name', 'age', 'hobby'] , l2 = ['jason', 18, 'DBJ'] 两个列表分别作为键值组成一个字典

    l1 = ['name', 'age', 'hobby']
    l2 = ['jason', 18, 'DBJ']
    
    # for 循环利用字典特性生成字典
    d = {}
    for i in range(len(l1)):
        d[l1[i]] = l2[i]
    print(d)
    # {'name': 'jason', 'age': 18, 'hobby': 'DBJ'}
    
    # 利用内置函数 zip,将 l1与l2 组合成元组,然后利用内置函数dict强转成字典
    d1 = dict(zip(l1, l2))
    print(d1, zip(l1, l2))
    # {'name': 'jason', 'age': 18, 'hobby': 'DBJ'} <zip object at 0x00000248171F21C8>
    
    # d2 将l1 与 l2 中的各元素分别作为键值组成一个新的字典,过滤掉 age 这一个键值   ---> 字典生成式
    d2 = {k: v for k, v in zip(l1, l2) if k != 'age'}
    print(d1, d2)
    # {'name': 'jason', 'age': 18, 'hobby': 'DBJ'} {'name': 'jason', 'hobby': 'DBJ'}

    集合生成式也可以同理推导出来(没有元组生成器)

    key_set = {i for i in l1 if i != "age"}  # 集合生成式
    print(se, type(se))
    # {'name', 'hobby'} <class 'set'>
    
    
    tp = (i for i in l1)  # 没有元组生成器
    print(tp, type(tp))
    for i in tp:
        print(i)
    # <generator object <genexpr> at 0x000001F21D24F0C8> <class 'generator'>
    # name
    # age
    # hobby

    生成器表达式的意义: 用来创建其他任何类型的序列,增加代码可读性一定程度上可以更高效 

    列表生成式与三元表达式结合小案例

    hello_list = ['halo', 'hi', 'nice to meet you']
    
    hello_list2 = [f"↑{item}" for item in hello_list if len(item) < 10]
    print(hello_list2)
    # ['↑halo', '↑hi']
    
    hello_list3 = [f"↑{item}" if len(item) < 10 else item for item in hello_list]  # 利用三元表达式实现不同处理
    print(hello_list3)
    # ['↑halo', '↑hi', 'nice to meet you']
    对不同类型元素采取不同处理

    匿名函数

    匿名函数: 没有名字的函数 

    特点: 临时存在,调用完立即销毁 

    关键字: lambda 

    示例:

    print(lambda x, y: x + y)  # lambda x, y: x + y 相当于是定义了一个函数
    # <function <lambda> at 0x000001DAC45B2E18>
    print((lambda x, y: x + y)(1, 3))  # (lambda x, y: x + y)(1, 3) 相当于是定义并调用了这个函数
    # 4
    
    # :左边的相当于函数的形参
    # :右边的相当于函数的返回值
    # 匿名函数通常不会单独使用,正常情况下是配合内置函数(也可以是自己写的函数)一起使用的

    python解释器自带的内置函数

     python3.6 中的内置函数

    max 求最大值、min 求最小值

    # 字典值比较,求出工资最高的那个人的名字
    d = {
        'egon': 30000,
        'swb': 88888888888,
        'nick': 3000,
        'tank': 1000
    }
    print(max(d, key=lambda name: d[name]))
    # swb
    print(min(d, key=lambda name: d[name]))
    # tank
    
    # key(函数的第二个关键字参数)那里返回什么,他就比较什么,最后返回的还是for 循环到的

    map 并行遍历(可接收一个自定义函数)

    # map 映射,给列表中的所有元素都 +5
    l = [1, 2, 3, 4, 5, 6]
    print(list(map(lambda x: x + 5, l)))  # 基于for循环
    # [6, 7, 8, 9, 10, 11]

    zip 并行遍历

    # zip 拉链  # 基于for循环
    l1 = [1, 2, ]
    l2 = ['jason', 'egon', 'tank']
    l3 = ['a', 'b', 'c']
    print(list(zip(l1, l2, l3)))
    # [(1, 'jason', 'a'), (2, 'egon', 'b')]

    filter 过滤

    # filter 过滤
    l = [1, 2, 3, 4, 5, 6]
    print(list(filter(lambda x: x != 3, l)))  # 基于for循环
    # [1, 2, 4, 5, 6]

    sorted 排序

    # sorted排序
    l = ['jason', 'egon', 'nick', 'tank']
    print(sorted(l, reverse=True))
    # ['tank', 'nick', 'jason', 'egon']

    reduce 合并(可指定初值)

    from functools import reduce  # 需要导包(感觉就不是内置的了)
    l = [1, 2, 3, 4, 5, 6]
    print(reduce(lambda x, y: x + y, l, 19))  # 19初始值  第一个参数
    # 40
    # 当初始值不存在的情况下 按照下面的规律
    #   第一次先获取两个元素 相加
    #   之后每次获取一个与上一次相加的结果再相加
  • 相关阅读:
    hadoop优点和缺点
    HDFS的基本shell操作,hadoop fs操作命令
    HDFS的java操作方式
    HDFS的体系结构和操作
    windows主机无法访问服务器
    用公共key实现无密码ssh
    hadoop2的伪分布部署
    lsof/fuser卸载挂载文件
    编译Apache Hadoop2.2.0源代码
    三十分钟掌握STL
  • 原文地址:https://www.cnblogs.com/suwanbin/p/11175910.html
Copyright © 2011-2022 走看看