函数递归
定义:函数在调用阶段直接或间接的又调用自身
小示例:
# 直接调用自身
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)) #指定参数,会一次从列表中取出一个值相加