函数递归,算法之二分法,表达式,生成式,匿名函数及常用内置函数

函数递归

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

  小示例:

# 直接调用自身
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))  #指定参数,会一次从列表中取出一个值相加
 

 



 

 

posted @ 2019-07-12 17:05  Key丶橙子哥  阅读(362)  评论(0编辑  收藏  举报