day12 递归、表达式、内置函数
#使命:让世界更有智慧
#愿景:更健康、更长久
#价值观:客户第一、团队合作、拥抱变化、本分、激情、敬业
#学以致用:编程的核心,是要解决人类的遇到各种问题,提升人类的差异化体验。
#公司选择:公司的产品服务,能不能直接让我们的生活更智能、更美好?
知识点:
一、函数递归和二分法
二、三元表达式与列表、字典表达式
三、匿名函数与内置函数
一、递归和二分法:
1.1 遇到问题:
# Ryan年龄:Ryan比*大2岁,*比**大2岁,**比***大2岁,***今年30岁
1.2 解决思路(逻辑思路、编程思路):
逻辑思路: # age(1)>>>age(2)+2>>>age(3)+2+2>>>age(4)+2+2+2>>>36
# 需要不断调用前一个改变的数,使用递归函数
编程思路: def age(n): if n==4: # 停止条件 return 30 return age(n+1)+2 print(age(1))
1.3 注意事项:
一个函数在内部调用自己的函数称为递归,递归次数在python里是有限的,默认是997次,所以写递归函数必须要有结束条件,也就是通过递归让问题变得简单这是与死循环的区别。
count=0 def func(): global count count+=1 print(count) func() func() #最大打印出997,最后报错:RecursionError
修改默认递归次数的方法(但是不建议修改,997次都不够,说明设置有问题,或者算法不对):
import sys sys.setrecursionlimit(修改后的值)
递归两个阶段:
1.回溯:就是一次次重复的过程,这个重复的过程必须建立在每一次重复问题的复杂度都应该下降,直到有一个最终的结束条件
2.递推:一次次往回推导的过程
# 递归函数不要考虑循环的次数 只需要把握结束的条件即可
1.4 应用拓展:
1、 算法之二分法:查找列表中是否有某个数字 # 二分法:容器类型里面的数字必须有大小顺序,如果没有需要通过.sort()进行排序
L = [2, 3, 4, 6, 7, 8, 9, 12, 34, 36, 45, 48, 57, 78, 79, 88, 90]
#兼容查找的数不存在的情况 def search(l,num,start=None,end=None): start=start if start else 0 end=end if end else len(l)-1 mid=(end-start)//2+start if start>end: return None elif l[mid]>num: return search(l,num,start,mid-1) elif l[mid]<num: return search(l,num,mid+1,end) elif l[mid]==num: return mid l = [2, 3, 4, 6, 7, 8, 9, 12, 34, 36, 45, 48, 57, 78, 79, 88, 90]print(search(l, 68))
2、数字n阶乘:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def func(n): if n==1: return 1 else: return n*func(n-1) print(func(7))
3、输出佩波那契数列的第n个数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def fib(n): if n==1 or n==2: return 1 return fib(n-1)+fib(n-2)
4、三级菜单实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
menu = { '北京': { '海淀': { '五道口': { 'soho': {}, '网易': {}, 'google': {} }, '中关村': { '爱奇艺': {}, '汽车之家': {}, 'youku': {}, }, '上地': { '百度': {}, }, }, '昌平': { '沙河': { '老男孩': {}, '北航': {}, }, '天通苑': {}, '回龙观': {}, }, '朝阳': {}, '东城': {}, }, '上海': { '闵行': { "人民广场": { '炸鸡店': {} } }, '闸北': { '火车战': { '携程': {} } }, '浦东': {}, }, '山东': {}, } def three_level_menu(menu): while True: for key in menu: print(key) k=input('>>>') if k=='q':return 'q' elif k=='b':break elif k in menu: ret=three_level_menu(menu[k]) if ret=='q':return 'q' three_level_menu(menu)
5、结构数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
编写⼀个函数从该结构数据中返回由指定的字段和对应的值组成的字典。如果指定字段不存在,则跳过该字段。 data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields:由"|"连接的以"fld"开头的字符串,如:fld2|fld3|fld7|fld19
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#思路一: def select(data,fields): result = {} field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: res = select(data[key],fields) result.update(res) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' print(select(data,fields))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#思路二: def select(data,fields,result = {}): field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: select(data[key], fields) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' select(data,fields) print(select(data,fields))
二、三元表达式
2.1 问题:有没有更简单的方式,去简化我们经常用的if...else
# 比较两个数的大小
def my_max(x,y): if x > y: return x else: return y
2.2 解决优化方案
x = 67854 y = 9897658 res = x if x > y else y # 如果if后面的条件成立返回if前面的值 否则返回else后面的值 print(res)
2.3 注意事项
三元表达式固定表达式 值1 if 条件 else 值2 条件成立 值1 条件不成立 值2 三元表达式的应用场景只推荐只有两种的情况的可能下,不推荐有多个选项、多重嵌套的 is_free = input('请输入是否免费(y/n)>>>:') is_free = '免费' if is_free == 'y' else '收费' print(is_free)
2.4 拓展应用
a)列表生成式:
--问题:如何更简单的把列表里面的元素进行修改,比如加上'_dmn'
l = ['高圆圆', '章子怡', '李嘉欣', '韩雪'] l1 = [] for i in l: l1.append('%s_dmn'%i) print(l1)
--解答:简化
res = ['%s_dmn'%i for i in l] print(res)
#答案 ['高圆圆_dmn', '章子怡_dmn', '李嘉欣_dmn', '韩雪_dmn']
--提升:在for后面加入if判断
# 先for循环依次取出列表里面的每一个元素 # 然后交由if判断 条件成立才会交给for前面的代码 # 如果条件不成立 当前的元素 直接舍弃 l2 = ['高圆圆_dmn', '章子怡', '李嘉欣_dmn', '韩雪_dmn', '杨颖'] res = [name for name in l2 if name.endswith('_dmn')] print(res)
b)字典生成式:
问题:如何通过三元表达式快速的将字典的内容表达出来
l1 = ['name', 'password', 'hobby'] l2 = ['ryan', '123', 'pb', 'apri'] d = {} for i,j in enumerate(l1): d[j] = l2[i] print(d) # {'name': 'ryan', 'password': '123', 'hobby': 'pb'}
解答:
l1 = ['Ryan','123','read'] d = {i:j for i,j in enumerate(l1) if j != '123'} print(d)
三、内置函数:
匿名函数:没有名字的函数,特点:临时存在用完就没了
def my_sum(x,y): return x + y res = (lambda x,y:x+y)(1,2) print(res) func = lambda x,y:x+y print(func(1,2)) # 左边的相当于函数的形参 # 右边的相当于函数的返回值 # 匿名函数通常不会单独使用,是配合内置函数一起使用
# map zip filter sorted reduce
max()
# map 映射 l = [1, 2, 3, 4, 5, 6] # print(list('hello')) 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')]
sort()
l = ['gao圆圆', 'zhang子怡', 'li嘉欣', 'han雪'] l.sort() print(l) # ['gao圆圆', 'han雪', 'li嘉欣', 'zhang子怡']
reduce()
from functools import reduce l = [1,2,3,4,5,6] print(reduce(lambda x,y:x+y,l,19)) # 19初始值 第一个参数 # 当初始值不存在的情况下 按照下面的规律 # 第一次先获取两个元素 相加 # 之后每次获取一个与上一次相加的结果再相加