zoukankan      html  css  js  c++  java
  • 函数递归,算法之二分法,表达式,生成式,匿名函数及常用内置函数

    函数递归

      定义:函数在调用阶段直接或间接的又调用自身

      小示例:

    # 直接调用自身
    def
    func(n): print('from func',n) func(n+1) func(1)
    # 间接调用自身
    def
    index(): print('from index') login() def login(): print('from login') index() login()

    这时的两个小示例都会无限之循环下去,不过python在内部做了优化,最多只能调用到998次左右,查看次数代码:

    import sys
    print(sys.getrecursionlimit())

    函数的递推分为两个阶段

      1.回溯:就是一次次重复的过程,这个重复的过程必须建立在每一次重复问题的复杂度都应该下降,知道有一个最终的结束条件

      2.递推:一次次往回推导的过程

    案例一

    假如现在有5个人,询问第一个人的年龄,第一个人说:我比第二个人大两岁,第二个人说比第三个人大两岁,依次类推,第五个人说:我今年18岁,写一个递归

    推导过程:

    age(5) = age(4) + 2

    age(4) = age(3) + 2

    age(3) = age(2) + 2

    age(2) = age(1) + 2

    age(1) = 18

    如果有第n个人,我们可以推出一个公式:age(n) = age(n-1) + 2      age(1) = 18      # 这时的n是已经说出自己年龄的那个人,所以我们根据n-1可得出上一个人的年龄

    def age(n):
        if n == 1:  # 必须要有结束条件
            return 18
        return age(n-1) + 2
    res = age(5)  #传入参数5
    print(res)

    案例二

    l = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,]]]]]]]]]]]]]

    将列表中的数字依次打印出来(循环的层数是你必须要考虑的点)

    推导思路:使用for循环打印列表,把列表中的值打印出来

    for i in l:
        if type(i) is int:
            print(i)
    
    打印结果
    1
    [2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,]]]]]]]]]]]]

      按照这个结果来看的话,如果有多少个列表那我们就得做多少次for循环,很显然,这个结果不是我们想得到的

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

    def get_num(l):
        for i in l:
            if type(i) is int:
                print(i)
            else:
                get_num(i)
    l1 = []
    for i in l1:
        print(i)

    算法之二分法

      定义:解决问题的高效率的方法

    l = [1,3,5,12,57,89,101,123,146,167,179,189,345]

      现在有一个列表,如何取出345这个值,大家肯定都会想到使用for循环,看345在不在列表l中,如果列表中就几万个值,让你取最后一个值,使用for循环岂不是很浪费资源,每个值都要循环。这时我们可以使用二分法,首先取出列表的总长度,然后除以2,取到中间部分的值,判断中间这个值是否大于或小于要取得这个值,如果大于,那我们则切分列表左边,再使用列表的总长度除以2,以此类推

    target_num = 101
    def get_num(l,target_num):
        if not l:
            print('不是这个值')
            return
        # 获取列表中间的索引
        print(l)
        middle_index = len(l) // 2
        # 判断target_num跟middle_index对应的数字的大小
        if target_num > l[middle_index]:
            # 切取列表右半部分
            num_right = l[middle_index + 1:]
            # 再递归调用get_num函数
            get_num(num_right,target_num)
        elif target_num < l[middle_index]:
            # 切取列表左半部分
            num_left = l[0:middle_index]
            # 再递归调用get_num函数
            get_num(num_left, target_num)
        else:
            print('找到了',target_num)
    
    get_num(l,target_num)

    三元表达式

    有两个值,分别是x和y,求他们两个的最大值

    def may_max(x,y):
        if x > y:
            return x
        return y
    res = may_max(30, 20)
    print(res)

      上述的代码,可以求出最大值是30,但是写了很多行代码,在我们可以使用一行代码简洁明了的写出上述代码,这种方式叫做三元表达式

    x = 99999
    y = 9898898
    res = x if x > y else y   # 三元表达式
    print(res)
    固定公式
    值1 if 条件 else 值2
        条件成立 值1
        条件不成立 值2

    注意:

      三元表达式的应用场景只推荐只有两种的情况的可能下使用

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

    列表生成式

    l = ['zhangsan', 'lisi', 'wangwu', 'maliu']

    在上述列表每一个名字后面加上_somebody

    l1 = []
    for name in l:
        l1.append('%s_somebody'%name)
        # l1.append(name + '_somebody')  # 在python不推荐使用+操作
    print(l1)

    使用列表生成式

    res = ['%s_somebody' %name for name in l]
    print(res)

    看了上面的示例之后,如何取出名字后面带有_somebody的名字呢?

    l = ['zhangsan_somebody', 'lisi_somebody', 'wangwu_somebody', 'maliu_somebody', 'xiaohong_ddd']

    res = [name for name in l if name.endswith('_somebody')]
    print(res)

    小总结:

    列表生成式的应用逻辑

      1.先for循环依次取出列表里面的每一个元素

      2.然后交由if判断  条件成立才会交给for前面的代码

      3.如果条件不成立 当前的元素 直接舍弃

    字典生成式

    和字典生成式一样,只是括号改变了

    l1 = ['zhangsan','123','read']

    d = {i:j for i,j in enumerate(l1) if j != '123'}
    print(d)
    res = {i for i in range(10) if i != 4}
    print(res)

    匿名函数

      定义:没有名字的函数       特点:临时存在用完就没了    关键字:lambda

    求x+y的值,使用函数

    def my_sum(x,y):
        return x + y
    res = my_sum(1,2)
    print(res)

    使用匿名函数

    res = (lambda x,y:x+y)(1,2)
    print(res)

    小总结:

      1.冒号左边的相当于函数的形参

      2.右边的相当于函数的返回值

      3.匿名函数通常不会单独使用,是配合内置函数一起使用的

    内置函数

      

    d = {
    'zhangsan':30000,
    'lisi':88888,
    'wangwu':3000,
    'maliu':1000
    }
    有一个字典,求谁的薪资最高
    可能会有人想到使用max求最大值,那么我们来测试一下
    res = max(d)
    print(res)
    
    打印结果   #zhangsan

      为什么会打印出张三,而不是lisi呢?因为使用max取求字典的最大值得时候默认比较的是key的最大值,在ascii码表中,z的排序最大,   A-Z排序65-69,a-z排序97-122.所以会打印zhangsan位结果,那么如何去做到比较value的值,打印出姓名为结果呢?

    print(max(d,key=lambda name:d[name]))

    map:映射(基于for循环)

    l = [1,2,3,4,5,6]
    print(list(map(lambda x:x+1,l)))   #每次打印列表中的数字自动+1

    zip:拉链(基于for循环)

    l1 = [1,2,3]
    l2 = ['jason','egon','tank']
    print(list(zip(l1,l2)))   # 两两组合,一一对应,如果了l1的值为1,2,3,4,5,也不会影响到1,2,3,匹配到的值

    filter:过滤(基于for循环)

    l = [1,2,3,4,5,6]
    print(list(filter(lambda x:x != 3,l)))  把数字3过滤掉

    sorted:排序

    l = [1,5,3,2,4,6]
    print(sorted(l))   # 升序
    print(sorted(l, reverse=True))  # 降序

    reduce:相当于一个加工厂

    from functools import reduce
    l = [1,2,3,4,5,6]
    print(reduce(lambda x,y:x+y,l))  #打印结果21  #在l后没有传参数的时候,他会把列表中多个元素,根据l前面的规则去整合成一个元素,第一次会一次取两个值,后面会一次取一个值,与上次相加的结果再相加
    print(reduce(lambda x,y:x+y,l,9))  #指定参数,会一次从列表中取出一个值相加
     


     

  • 相关阅读:
    javascript作用域
    [翻译]Review——How JavaScript works:The building blocks of Web Workers
    [转]Shared——回调函数是什么
    由上一个血案引发的关于property和attribute关系的思考
    RN canvas画布大小之谜
    [转]Tips——Chrome DevTools
    Algorithm——无重复字符的最长子串
    [翻译]Review——The Inner Workings Of Virtual DOM
    Tips——单页面内的多重跳转路由使用
    [转]Shared——Javascript中的call详解
  • 原文地址:https://www.cnblogs.com/chengzige/p/11177203.html
Copyright © 2011-2022 走看看