递归&二分法&三元表达式&生成式&匿名函数

image

1. 递归函数

递归:函数在运行过程中,直接或间接的调用了自身。

# 关于递归深度
# 官网表述:python默认的最大递归深度为1000次,代码跑出来可能997,998.
# 查看最大递归深度
import sys
print(sys.getrecursionlimit())
# 更改最大递归深度
sys.setrecursionlimit(2000)

# 直接调用自身
def index():
	print('from index')
	index()

index()

# 间接调用自身
def func():
	print('from func')
	test()

def test():
	print('from test')
	func()

func()

但是以上两种情况都没有什么意义。

递归分为两个阶段:

  1. 递推
    1. 一层层往下推到答案(每次递推之后复杂度相较于上一次一定要有所下降)
  2. 回溯
    2. 根据最后的结论往前推导出最初需要的答案。

注意:递归一定要有结束条件!!!!!!!

# 伪代码:可能无法运行,但是可以表达逻辑
age(5) = age(4) + 2
age(4) = age(3) + 2
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 18

def get_age(n):
	# 递归要有结束条件
	if n == 1:
		return 18
	return get_age(n-1) + 2


print(get_age(5))
# 这是递归函数真正的用途

举例

l = 1,[2,[3,[4,[5,[6,[7,[8,[9,[10,]]]]]]]]]
# 要求:打印出列表种每一个数字

def get_num(lis):
	for i in lis:
		if type(i) is int:
			print(i)
		return get_num(i)

get(l)
# 因为for循环列表种没有元素之后会自动停止,所以不用额外加上结束条件。

2. 算法之----二分法

什么是算法????
解决问题的最佳(高效)方法。


# 二分法能够使用的场景:数据集必须有序.
l1 = [3,9,12,23,35,42,56,64,77,89,94,108,112,120,139,147,158,169,173]

# 要求:在列表中找出目标数字
# 二分法的思维,将数据集一分为二,不断重复,直到找到目标。

def find_num(target_num, lis):
	# 还要想到一种情况:目标数字不在列表当中
	if len(lis) == 0:  # 列表找空了,没找到
		print('没有找到target_num:{}'.format(target_num))
		return
	# 先获取中间位置的索引值
	mid_index = len(lis)//2
	# 判断目标数字与中间位置索引对应的数字大小关系
	if target_num > lis[mid_index]:
		# 说明目标数字在列表中间索引右侧
		lis_r = lis[mid_index + 1: ]   # 切片取值
		# 继续调用该函数
		find_num(target_num,lis_r)
	elif target_num < lis[mid_index]:
		# 说明目标数字在列表中间索引左侧
		lis_l = lis[: mid_index]  # 切片取值
		# 继续调用该函数
		find_num(target_num,lis_l)
	else:
		# 中间索引值对应数字恰好是目标数字
		print('找到了target_num:{}'.format(target_num))


find_num(42, l1)
# 找到了target_num:42
find_num(111, l1)
# 没有找到target_num:111

3. 三元表达式(三目运算)

def my_max(a, b):
	if a > b:
		return a
	else:
		return b

# 当功能需求仅仅是二选一的情况下,则推荐使用三元表达式
def my_max(a, b):
	return a if a > b else b

"""
条件成立取的值 if 条件 else 条件不成立取的值
三元表达式尽量不要嵌套使用,本身就是为了简洁,不要搞复杂了。
"""
is_free = input('电影是否收费(y/n)>>>:').strip()
print('收费' if is_free == 'y' else '免费')

4. 生成式

  • 列表生成式

    # 传统方法
    name_list = ['jason', 'jack', 'joshua', 'tony']
    # 要求给列表中所有的人名加上_DSB后缀
    # 1. 定义一个空列表
    new_list = []
    # 2. 循环旧列表
    for name in name_list:
    	new_name = '{}_DSB'.format(name)
    	new_list.append(new_name)
    
    
    # 列表生成式做法
    lis_method = [ '{}_DSB'.format(name) for name in name_list]
    print(lis_method)
    
    # 将列表中所有的人名后面加上_DSB,jason除外,打印出其他人
    res = ['{}_DSB'.format(name) for name in name_list if name != 'jason']
    print(res)
    # 这已经是最复杂的情况了
    # 因为for循环和if 都可以和else一起用,所以此处后面不能加else了。
    
  • 字典生成式
    枚举法enumerate
    针对该方法使用for循环取值,每会产生两个结果
    第一个是从0开始的数字
    第二个是被循环对象里面的元素
    还可以通过start参数控制起始数字

    li = ['jason', 'joshua', 'jack',
    for i, j in enumerate(li):
        print(i, j)
    
    """
    0 jason
    1 joshua
    2 jack
    3 alex
    4 tony
    """
    for k, v in enumerate(li, 2):
        print(k, v)
    
    """
    2 jason
    3 joshua
    4 jack
    5 alex
    6 tony
    """
    
    

    正题

    name_list = ['jaosn','jack','tony','joshua']
    res = {i:j for i,j in enumerate(name_list if j == 'jason')}
    print(res)
    
    # 同理集合也有生成式
    # 只有元组是特殊的,生成一个迭代器。后面会说到。
    

5. 匿名函数

顾名思义就是没有名字的函数

# 语法格式
lambda 形参: 返回值
print( (lambda x: x**2)(2))
# 4


# map() 映射
"""
map函数的原型是map(function, *iterables),它的返回结果是一个列表。
参数function传的是一个函数名,可以是python内置的,也可以是自定义的。
参数iterable传的是一个可以迭代的对象,例如列表,元组,字符串这样的。可以支持传多个可迭代对象。
这个函数的意思就是将function应用于iterable的每一个元素,结果以列表的形式返回。
"""

l = [1, 2, 3, 4, 5, 6, 7, 89,]
print(list(map(lambda x: x**2, l))
# [1, 4, 9, 16, 25, 36, 49, 7921]


image

posted @ 2021-11-18 17:06  Joshua_jiaxue  阅读(90)  评论(0)    收藏  举报