# 函数的递归
# 函数在调用阶段直接或间接的又调用自身
# # 补充
# import sys # 导入系统模块
# print(sys.getrecursionlimit()) # 不是很精确 # 计算最大递归次数
# sys.setrecursionlimit(2000) # 修改最大递归次数
#
# def func(n): # 定义一个函数 形参n
# print('from func',n) # 打印 字符串和变量n
# func(n+1) # 自身函数内调用自己 并且传形参 n + 1
# func(1) # 调用函数,传实参 = 1,这个可以计算递归次数,自己调用自己,死循环最大递归998
# def index(): # 定义一个函数1
# print('from index') # 打印字符串
# login() # 调用函数2
#
# def login(): # 定义一个函数2
# print('from login') # 打印字符串
# index() # 调用函数1
# login() # 执行死循环 报错,超过最大递归次数,一次递归会开一次局部名称空间,占内存
# 函数不应该无限制的递归下去
# 递归
"""
递归分为两个阶段
1.回溯:就是一次次重复的过程,这个重复的过程必须建立在每一次重复问题的复杂度都应该下降
直到有一个最终的结束条件
2.递推:一次次往回推导的过程
"""
"""
age(5) = age(4) + 2
age(4) = age(3) + 2
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 18
age(n) = age(n-1) + 2 # n > 1
age(1) = 18 # n = 1 可以作为终止循环的条件,n = 1 return返回18
"""
#
# # 递归函数
# def age(n): # 用递归函数解决上面的问题
# if n == 1: # 必须要有结束条件 如果n等于1 age(1) = 18 就返回18
# return 18 # 就返回18
# return age(n-1) + 2 # 不是age(1)就返回 age(n-1) + 2
# res = age(5) # age(5)赋值给res
# print(res) # 打印res
# l = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,]]]]]]]]]]]]]
# 将列表中的数字依次打印出来(循环的层数是你必须要考虑的点)
# for i in l: 推导思路 这个有多少个值就需要写多少次if循环
# 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:
# def index(): # 代码行的占位符 推荐使用pass
# # pass # 第一种顶替方式(推荐使用pass)
# # ... # 第二种顶替方式
# index()
# # 递归函数不要考虑循环的次数 只需要把握结束的条件即可
# l = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,]]]]]]]]]]]]]
# def get_num(l): # 定义一个函数
# for i in l: # 从列表中循环取值
# if type(i) is int: # 如果取出来的值是整型
# print(i) # 就打印
# else: # 其他情况
# get_num(i) # 继续执行该函数并且把不是整型的这个数据,放给for循环继续取值 继续判断
# get_num(l) # 定义完函数,直接调用
# # 空列表中循环取值,取不到不会报错
# l1 = []
# for i in l1:
# print(i)
# # 算法:解决问题的高效率的方法
# l = [1,3,5,12,57,89,101,123,146,167,179,189,345] # 定义一个列表
# num = 345 # 想要从列表中找的值
# for i in l: # 循环从列表中依次取值
# if num == i: # 如果我们要找的值取到了
# print('find it') # 就打印找到了
# # 这种方法再列表中找值,效率很低,需要找完整个列表,循环次数比较多
# # 二分法:容器类型里面的数字必须有大小顺序
# # 先获取列表中间的索引值,列表长度除以2,取整,比较这个值跟目标值是否相等,比较大小,因为二分法找的这个容器中数字是按大小排序的
# #,如果大于目标值,则从中间索引往大的方向,继续取中间值索引,再做循环比较,再次循环,直到找到目标值
# l = [1,3,5,12,57,89,101,123,146,167,179,189,345] # 定义一个列表
# target_num = 666 # 定义目标值
# def get_num(l,target_num): # 定义查找算法函数
# if not l: # 先判断目标值在不在列表
# print('你给的工资 这个任务怕是没法做') # 如果不在 提示
# return # 不在就直接跳出函数,不找了
# # 获取列表中间的索引
# print(l) # 打印整个列表
# middle_index = len(l) // 2 # 取中间值索引,用列表长度除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('find it',target_num) # 即命中目标值
# get_num(l,target_num) # 调用函数,传值目标列表和目标值
# def my_max(x,y):
# if x > y:
# return x
# else:
# return y
# """
# 当x大的时候返回x当y大的时候返回y
# 当某个条件成立做一件事,不成立做另外一件事
# """
# x = 99999
# y = 9898898
# res = x if x > y else y
# print(res)
# # 如果if后面的条件成立返回if前面的值 否则返回else后面的值
'''
x = 99999
y = 9898898
res = x if x > y else y
如果if后面的条件成立返回if前面的值 否则返回else后面的值
'''
"""
三元表达式固定表达式
值1 if 条件 else 值2
条件成立 值1
条件不成立 值2
三元表达式的应用场景只推荐只有两种的情况的可能下
"""
# x = 1
# y = 2
# m = 3
# n = 4
# res = x if x > y else (m if m >n else (...)) 不能这样嵌套使用
# 三元表达式的应用场景只推荐只有两种的情况的可能下
'''
三元表达式的应用场景只推荐只有两种的情况的可能下
'''
# # 案例1
# is_free = input('请输入是否免费(y/n)>>>:')
# is_free = '免费' if is_free == 'y' else '收费'
# print(is_free)
# # 案例2
# username = input('username>>>:')
# res = 'NB' if username == 'jason' else '垃圾'
# print(res)
# l = ['tank','nick','oscar','sean'] # 定义一个列表
# l1 = [] # 定义一个空列表
# for name in l: # 循环取值
# l1.append('%s_sb'%name) # 循环拼接字符串
# # l1.append(name + '_sb') # 不推荐使用 效率低,占内存
# print(l1) # 打印新列表
# # 列表生成式
'''
res = ['%s_DSB'%name for name in l] # 从列表l中循环取值,赋值给name,再交给前面字符串拼接
'''
# l = ['tank_sb', 'nick_sb', 'oscar_sb', 'sean_sb','jason_NB']
# res = ['%s_DSB'%name for name in l]
# print(res)
# # 结果为 ['tank_sb_DSB', 'nick_sb_DSB', 'oscar_sb_DSB', 'sean_sb_DSB', 'jason_NB_DSB']
#
# res = [name for name in l if name.endswith('_sb')] # 后面不支持再加else的情况
# print(res)
# 结果为 ['tank_sb', 'nick_sb', 'oscar_sb', 'sean_sb'] 没有jason
# # 先for循环依次取出列表里面的每一个元素
# # 然后交由if判断 条件成立才会交给for前面的代码
# # 如果条件不成立 当前的元素 直接舍弃
'''
res = [name for name in l if name.endswith('_sb')]
从列表l中循环取值,赋值给name,
先交给if判断是否满足条件
满足条件交给前面字符串拼接,不满足直接舍弃
'''
# # 字典生成式
# l1 = ['name','password','hobby'] # 定义列表1
# l2 = ['jason','123','DBJ','egon'] # 定义列表2
# d = {} # 定义空字典
# for i,j in enumerate(l1): # 枚举列表l1 得到索引和元素对应关系,索引从0开始
# d[j] = l2[i] # 用key和value定义字典,key是第一个列表取出的元素,value是第二个列表中按第一个列表的索引取值
# print(d) # 打印结果为 {'name': 'jason', 'password': '123', 'hobby': 'DBJ'}
#
# l1 = ['jason','123','read']
# d = {i:j for i,j in enumerate(l1) if j != '123'}
# print(d)
''''''
'''
d = {i:j for i,j in enumerate(l1) if j != '123'}
# 定义键值对i:j 循环从列表1枚举后取值i,j,i为索引,j为列表元素,
如果j不等于123,交给前面组成键值对形成字典,如果等于123,则舍弃
'''
# ''''''
'''
集合生成式
'''
# res = {i for i in range(10) if i != 4}
# # 集合生成式 ,集合元素为i, 循环从范围0-10取值,不取10,赋值给i,组成集合
# print(res)
# # 打印结果为 {0, 1, 2, 3, 5, 6, 7, 8, 9}
#
#
'''
生成器表达式
'''
# res1 = (i for i in range(10) if i != 4) # 这样写不是元组生成式 而是生成器表达式
# # 生成器表达式,元素为i, 循环从范围0-10取值,不取10,赋值给i,如果i不等于4,交给前面生成器,不打印
# print(res1)
# # 打印结果为 <generator object <genexpr> at 0x000001C9444FEFC0> 结果是生成器内存地址
#
# # 从生成器中循环取值,打印就是一个一个的值
# for i in res1:
# print(i)
# 匿名函数
"""
没有名字的函数
匿名函数的特点
临时存在用完就没了
"""
# def my_sum(x,y): # 定义一个函数,位置形参x,y
# return x + y # 运行函数则返回两个参数之和
#
'''
lambda 匿名函数
res = (lambda x,y:x+y)(1,2)
直接将函数结果赋值给res = (声明匿名函数,有两个参数x,y:对参数的操作为相加) 传参(1,2)
# :冒号的左边的相当于 函数的形参 形参:函数返回值
# :冒号的右边的相当于 函数的返回值
# 匿名函数通常不会单独使用,是配合内置函数一起使用
'''
# res = (lambda x,y:x+y)(1,2)
# print(res)
# func = lambda x,y:x+y
# print(func(1,2)) # 也可以用函数承接匿名函数 , 然后加括号传参运行
# :左边的相当于函数的形参
# :右边的相当于函数的返回值
# 匿名函数通常不会单独使用,是配合内置函数一起使用
# l = [1,2,3,4,5]
# print(max(l)) # 内部是基于for循环的 来求最大值
"""
ASCII码表 字母对应的十进制数字
# A-Z 65 90
# a-z 97 122
print(chr(97)) # 查看ASCII码表中97对应的是哪个字符 输出 a
"""
# print(chr(97)) # 查看ASCII码表中97对应的是哪个字符 输出 a
# # 比较薪资 返回人名
# d = {
# 'egon':30000,
# 'jason':88888888888,
# 'nick':3000,
# 'tank':1000
# } # 定义字典
# def index(name): # 定义函数(位置形参name)
# return d[name] # 返回字典中key为name的值
#
# print(max(d,key=lambda name:d[name]))
#
'''
打印(求职大值函数的结果,(目标是一个字典d,返回的肯定是字典d的key,即人名;
key是指定函数,max会按key指定的函数来比较大小,求最大值,指定key是一个lambda匿名函数,
匿名函数需要从目标中传入name变量,即从字典中只能取到key做name变量的值,
后面key指定的匿名函数返回值为该name变量对应的d字典中的value,即max做运算时,会按key指定的函数来比较,即比较字典中的value)
max函数运算结束返回值是从字典d中取,即只能返回key,即 返回 key指定的函数执行结果运算后的value所对应的d字典的key
'''
# print(min(d,key=lambda name:d[name]))
#
'''
min()内置函数和max()内置函数,同理
'''
# 将五个内置函数
'''
map 映射
zip 拉链
filter 过滤
sorted 排序
reduce 累积
'''
# # map 映射
# l = [1,2,3,4,5,6]
# print(list('hello')) # 结果为 ['h', 'e', 'l', 'l', 'o']
# print(list(map(lambda x:x+5,l))) # 基于for循环
# # 打印新列表,列表中将元素一一对应,对应方式是一个lambda匿名函数,x取值变量,取到值将x+5,map对象是一个列表l
# # 效果就是将列表中的所有元素挨个对应的+5,原理是基于for循环 结果为 [6, 7, 8, 9, 10, 11]
# # 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')]
'''
zip循环从每个对象中一次取值,基于for循环取值,
取到值之后将每个对象中同一次循环出来的值作为一个元组,循环多次将多个元组放在一个列表中
类似将多个容器值一一对应放在一起,像拉链的锯齿对应,如果有容器对象的值数量不够,则按对少的数量来组,不会报错
就像拉链锯齿对不上了就不再拉了
'''
# l = [1,2,3,4,5,6]
# print(list(filter(lambda x:x != 3,l))) # 基于for循环
# # 结果为 [1, 2, 4, 5, 6]
'''
打印,列表中用filter方法,按照lambda匿名函数过滤,循环取x变量,基于for循环
过滤变量,如果x不等于3,则交给外层list组成列表,过滤对象为列表l
'''
# #
# l = ['jason','egon','nick','tank']
# res1 = l.sort()
# print(id(l.sort()),res1) # 1544529104 None 没有返回值,直接操作原列表,这个id是None的
# res = sorted(l,reverse=True)
# print(id(l)) # 2402417808456
# print(id(res)) # 2402417808392 id不一致,sorted不是修改原列表,是生成一个新列表
# print(sorted(l,reverse=True))
# # 结果为 ['tank', 'nick', 'jason', 'egon']
'''
打印,排序方法结果,对象是列表l,逗号隔开指定方法,方法是倒叙,不指定默认是正序
按字母排序就是按字母对应的ASCII码表的十进制来比较大小,字母越靠前数值越小,即字符越小
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,无返回值,
而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
'''
#
# # reduce
# from functools import reduce
# l = [1,2,3,4,5,6]
# print(reduce(lambda x,y:x+y,l,19)) # 19初始值 第一个参数
'''
打印,reduce方法的结果,定义一个匿名函数,有参数x,y 指定方法为x+y ,指定取值对象是列表l,指定初始值为19
如果指定初始值为19,则运算为取出第一个值加19,再取出第二个值加前面的和,依次循环
如果不指定初始值,默认初始值为列表中的第一个元素,即取出前两个元素相加,然后再取出第三个元素加前两个的和,再取一个值依次循环
'''
# 当初始值不存在的情况下 按照下面的规律
# 第一次先获取两个元素 相加
# 之后每次获取一个与上一次相加的结果再相加
# def age(n):
# age(5) = 18
# age(n+1) = age(n) + 2
# return age
# age(1)
# list1 = [2,3,1,5]
# len(list1)
# def func():
# list[len(list.sort()) // 2] > n :
# func()
# target_num = 123
# def get_num(l,target_num):
# mid_num = len(list1) // 2
# if mid_num > target_num :
# l_left = list1[0:mid_num]
# elif mid_num < target_num :
# l_right = [mid_num+1:]
# else:
# print(target_num)