十五.叠加多个装饰器,函数的递归调用,匿名函数

一.同时叠加多个装饰器:加载顺序与执行顺序(*****)

案例1:

# 解析加载与执行过程
def deco1(func1): # func1 = wrapper2
	def wrapper1(*args,**kwargs):
		print('=====>wrapper1')
		res1 = func1(*args,**kwargs) #  wrapper2 ==>未完
		return res1
	return wrapper1

def deco2(func2): # func2 = wrapper3
	def wrapper2(*args,**kwargs):
		print('=====>wrapper2')
		res2 = func2(*args,**kwargs)  # wrapper3 ==>未完
		return res2
	return wrapper2

def deco3(func3): # func3 = index
	def wrapper3(*args,**kwargs):
		print('======>wrapper3')
		res3=func3(*args,**kwargs)  # index==>未完
		return res3
	return wrapper3

		# index = wrapper1

@deco1  # deco1(wrapper2)==>wrapper1
@deco2  # deco2(wrapper3)==>wrapper2
@deco3  # deco3(index)=====>wrapper3
def index():
	print('from index')
	return 123

res = index()  # res=wrapper1()
# ======>wrapper1
# ======>wrapper2
# ======>wrapper3
# from index

在这里插入图片描述

结论:

1.装饰器的加载顺序是自下而上的
2.装饰器的执行顺序是自上而下的

案例2:

import time
def timmer(func):
	def wrapper1(*args,**kwargs):
		print('===>wrapper1')
		start = time.time()
		res = func(*args,**kwargs)
		stop = time.time()
		print(stop - start)
		return res
	return wrapper1

def auth(func):
	def wrapper2(*args,**kwargs):
		print('=====>wrapper2')
		name=input('请输入您的账号: ').strip()
		pwd=input('请输入您的密码: ').strip()
		if name == 'egon' and pwd == '123':
			print('登录成功')
			res = func(*args,**kwargs)
			return res
		else:
			print('账号密码错误')

	return wrapper2

@auth
@timmer
def index():
	time.sleep(1)
	print('from index')

# wrapper2=>wrapper1=>index
index()  # wrapper1()

二.函数的递归调用

1.什么是函数的递归调用

函数的递归调用指的是在调用一个函数的过程中又直接或间接地调用了自己
函数的递归调用就是一个循环的过程

# 直接调用自己
def f1():
	print('fffff')
	f1()
f1()
# 间接调用自己
def f1():
	print('from f1')
	f2()
def f2():
	print('from f2')
	f1()
f1()

2.递归调用的特点

python没有尾递归优化(了解)

递归调用应该遵循一个大前提:

必须在满足某种条件下结束递归调用,然后向上一层一层返回

递归调用经历2个阶段

1.回溯:向下一层一层地调用
2.递推:在某一层终止调用,开始向上一层一层返回

案例1(薪资):

salary(5) = salary(4) + 1000
salary(4) = salary(3) + 1000
salary(3) = salary(2) + 1000
salary(2) = salary(1) + 1000
salary(1) = 3000

salary(n) = salary(n-1) + 1000 # n > 1
salary(1) = 3000               # n = 1
def salary(n):
	if n == 1:
		return 3000
	return salary(n-1) + 1000

res = salary(4)
print(res)

总结:

递归调用就是一个循环的过程,循环的次数取决于何时结束调用自身

案例2(循环取出嵌套列表的值):

list1 = [1, [2, [3, [4, [5, [6, [7, [9, ]]]]]]]]
def func(nums_l):
	for x in nums_l:
		if type(x) is list:
			func(x)
		else:
			print(x)
			
func(list1)

案例3(二分法):

#有一个有序排列的数字列表
nums = [-3, 1, 5, 7, 11, 13, 21, 37, 45]

方案一(for 循环):整体遍历,效率低

nums = [-3, 1, 5, 7, 11, 13, 21, 37, 45]
find_num = 45
for num in nums :
	if find_num == num:
		print('找到啦')
		break
else:
	print('不存在')

方案二:二分法

算法:二分法查找适用于数据量较大时,但是数据需要先排好顺序。

nums = [-3, 1, 5, 7, 11, 13, 21, 37, 45]
find_num = 47

def search(find_num,nums):
	print(nums)
	if len(nums) == 0:
		print('不存在')
		return
	mid_index = len(nums) // 2
	if find_num > nums[mid_index]:
		# 查找范围: 右半部分
		new_nums = nums[mid_index+1:]
		search(find_num,new_nums)
	elif find_num < nums[mid_index]:
		new_nums = nums[:mid_index]
		search(find_num,new_nums)
	else:
		print('找到了')
search(find_num,nums)

三.匿名函数

匿名函数指的是没有名字的函数

匿名函数只用于临时使用一次的场景

# 以此为例,对照着写匿名函数
def f(x,y):
	return x+y
#匿名函数错误写法:太过麻烦	
f = (lambda x,y: x+y)
print(f)
res = f(1,2)
print(res)
# 正确匿名函数写法
res=(lambda x,y: x + y)(1,2)
print(res)

匿名函数通常用于与其他函数配合使用

应用场景如下:
取薪资最高的人名

salaries = {
    "zegon": 3600,
    "lxx": 3000,
    "axx": 4000
}
# max 可以用来取出最大值
print(max([22,333,44,555]))

# 取薪资最高的那个人的人名
#方式一(有名函数)
def func(k):
	return salaries[k]
print(max(salaries,key=func))
# 方式二(匿名函数):
print(max(salaries,key=lambda k:salaries[k]))
# 取出工资最低的人的人名
print(min(salaries,key=lambda k:salaries[k]))
#按照工资高低给人名排序
# sorted(默认从低到高)
print(sorted(salaries,key=lambda k:salaries[k]))

# 加上reverse=True(从高到底)
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))

猜你喜欢

转载自blog.csdn.net/yikenaoguazi/article/details/106860042
今日推荐