【修仙】第一卷 初出茅庐 第十七章 装饰器2
前情提要
闭包函数
闭包函数的定义
定义在函数内部的函数,并且使用了外部函数局部命名空间的名字
闭包函数的作用
闭包函数给我们提供了另一种给函数体代码传参的方式
装饰器简介
装饰器准则
不改变被装饰函数源代码 不改变被装饰函数调用方式
装饰器重要推导流程
# 1.统计某个函数的运行时间
import time
def func():
time.sleep(1)
return 123
start_time = time.time()
res = func()
print(res)
end_time = time.time()
print(f'总共消耗了{end_time-start_time}秒')
# 2.将统计函数运行时间的代码封装成了函数
import time
def func():
time.sleep(1)
return 123
def get_time():
start_time = time.time()
res = func()
print(res)
end_time = time.time()
print(f'总共消耗了{end_time - start_time}秒')
get_time()
# 3.直接封装成函数会改变调用方式
import time
def func():
time.sleep(1)
return 123
def home():
time.sleep(2)
return 1234
def get_time(func_name):
start_time = time.time()
res = func_name()
print(res)
end_time = time.time()
print(f'总共消耗了{end_time - start_time}秒')
get_time(func)
get_time(home)
# 4.利用闭包函数传参
import time
def func():
time.sleep(1)
return 123
def home():
time.sleep(2)
return 1234
def get_time(func_name):
def inner():
start_time = time.time()
res = func_name()
print(res)
end_time = time.time()
print(f'总共消耗了{end_time - start_time}秒')
return inner
res = get_time(func)
res()
res1 = get_time(home)
res1()
# 5.利用重名替换原来函数名的功能
...
...
func = get_time(func)
func()
home = get_time(home)
home()
# 6.函数的参数
import time
def func():
time.sleep(1)
return 123
def home():
time.sleep(2)
return 1234
def get_time(func_name):
def inner(*args, **kwargs):
start_time = time.time()
res = func_name(*args, **kwargs)
print(res)
end_time = time.time()
print(f'总共消耗了{end_time - start_time}秒')
return inner
func = get_time(func)
func()
home = get_time(home)
home()
# 7.函数的返回值
import time
def func():
time.sleep(1)
return 123
def home():
time.sleep(2)
return 1234
def get_time(func_name):
def inner(*args, **kwargs):
start_time = time.time()
res = func_name(*args, **kwargs)
print(res)
end_time = time.time()
print(f'总共消耗了{end_time - start_time}秒')
return res
return inner
func = get_time(func)
func()
home = get_time(home)
home()
装饰器模板
def outer(func_name):
def inner(*args, **kwargs):
print('这里执行被装饰函数执行前的操作')
res = func_name(*args, **kwargs)
print('这里执行被装饰函数执行后的操作')
return res
return inner
装饰器语法糖
def outer(func_name):
def inner(*args, **kwargs):
print('这里执行被装饰函数执行前的操作')
res = func_name(*args, **kwargs)
print('这里执行被装饰函数执行后的操作')
return res
return inner
@outer # 语法糖 可以看做 func = outer(func)
def func():
passs
装饰器修复技术
修复技术作用
让函数更像函数
from functools import wraps
def outer(func_name):
@wraps(func_name) # 就两句 这一句 上面导入一句
def inner(*args, **kwargs):
print('这里执行被装饰函数执行前的操作')
res = func_name(*args, **kwargs)
print('这里执行被装饰函数执行后的操作')
return res
return inner
今日内容
今日内容概要
- 多层装饰器
- 有参装饰器
- 递归函数
- 算法(二分法)
多层装饰器
def outer1(func1):
print('加载了outer1')
print(f'func1: {func1}')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outer2(func2):
print('加载了outer2')
print(f'func2: {func2}')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outer3(func3):
print('加载了outer3')
print(f'func3: {func3}')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outer1 # outer2 = outer1(outer2)
@outer2 # outer3 = outer2(outer3)
@outer3 # index = outer3(index)
def index():
print('from index')
index()
# 运行结果
# 加载了outer3
# func3: <function index at 0x000002E9F5578820>
# 加载了outer2
# func2: <function outer3.<locals>.wrapper3 at 0x000002E9F55788B0>
# 加载了outer1
# func1: <function outer2.<locals>.wrapper2 at 0x000002E9F5578940>
# 执行了wrapper1
# 执行了wrapper2
# 执行了wrapper3
# from index
有参装饰器
作用
在装饰器内部可以切换多种数据来源
def outer_1(name):
def outer(func_name):
def inner(*args, **kwargs):
print(f'这里操作的是{name}')
res = func_name(*args, **kwargs)
return res
return inner
return outer
@outer_1('学生') # @outer outer = outer_1('学生')
def student():
pass
@outer_1('老师') # @outer outer = outer_1('老师')
def teacher():
pass
递归函数
递归函数概念
函数直接或者间接调用了自己
# 直接调用
count = 0
def index(count):
if count == 4:
print('执行了4次')
return
print(count)
count += 1
index(count)
index(count)
# 运行结果
# 0
# 1
# 2
# 3
# 执行了4次
# 间接调用
count = 0
def func1(count):
if count == 4:
print('总共执行了4次')
return
print(f'这里是func1:{count}')
count += 1
func2(count)
def func2(count):
if count == 4:
print('总共执行了4次')
return
print(f'这里是func2:{count}')
count += 1
func1(count)
func1(count)
# 运行结果
# 这里是func1:0
# 这里是func2:1
# 这里是func1:2
# 这里是func2:3
# 总共执行了4次
递归最大限制
既python中允许函数递归调用的次数
官方给出的限制是1000 用代码去验证可能会有些许偏差(997 998...)
count = 0
def func(count):
print(count)
count += 1
func(count)
func(count)
# 最终结果停在了995后就报错了 也可能996 997 不精确 有偏差
递归应用场景
递推:一层层往下寻找答案
回溯:根据已知条件推导最终结果
递归要求
每次调用的时候都必须要比上一次简单!!!
并且递归函数最终都必须要有一个明确的结束条件!!!
算法(二分法)
算法的定义
解决问题的方法
二分法
局限性:数据要有序排列;当数据在开头或结尾时,比顺序查找费时间
# 在有序列表中查找数据是否存在(二分法)
# 解决办法1:切割数据
l1 = [1, 2, 5, 6, 8, 11, 23, 45, 67, 89, 123, 245, 321, 454, 554, 567, 754, 765, 875]
count = 0
def func(target_list, target_num):
if len(target_list) == 0:
print('没有查找到')
return
global count
count += 1
middle_index = len(target_list) // 2
middle_value = target_list[middle_index]
if middle_value < target_num:
target_list = target_list[middle_index + 1:]
func(target_list, target_num)
elif middle_value > target_num:
target_list = target_list[:middle_index]
func(target_list, target_num)
else:
print(f'找到了 共查了{count}次')
while True:
target_num = input('请输入需要查找的数据值>>>:').strip()
if not target_num.isdigit():
print('请输入正确数值')
continue
target_num = int(target_num)
func(l1, target_num)
# ------------------------------------------------------------------------
# 解决办法2:索引变更
l1 = [1, 2, 5, 6, 8, 11, 23, 45, 67, 89, 123, 245, 321, 454, 554, 567, 754, 765, 875]
count = 0
def func(target_num, start_index=0, end_index=len(l1)):
if start_index > end_index:
print('没查找到')
return
global count
count += 1
middle_index = (start_index + end_index) // 2
middle_value = l1[middle_index]
if middle_value < target_num:
func(target_num, middle_index, end_index)
elif middle_value > target_num:
func(target_num, start_index, middle_index)
else:
print(f'找到了 共查找了{count}, 在l1中的索引值为{middle_index}')
while True:
target_num = input('请输入需要查找的数据值>>>:').strip()
if not target_num.isdigit():
print('请输入正确数值')
continue
target_num = int(target_num)
func(target_num)
作业
# 1.尝试编写有参函数将多种用户验证方式整合到其中
# 直接获取用户数据比对
# 数据来源于列表
# 数据来源于文件
def date_type(date_type):
def outer(func_name):
def inner(*args, **kwargs):
if date_type == '直接调用':
print('你直接调用了数据')
res = func_name(*args, **kwargs)
return res
elif date_type == '列表':
print('你通过列表调用了数据')
res = func_name(*args, **kwargs)
return res
elif date_type == '文件':
print('你通过文件调用了数据')
res = func_name(*args, **kwargs)
return res
else:
print('李在赣神魔! 你的操作有问题')
return inner
return outer
@date_type('直接调用')
def from_user():
pass
@date_type('列表')
def from_list():
pass
@date_type('文件')
def from_file():
pass
from_user()
from_list()
from_file()
# 2.尝试编写递归函数
# 推导指定某个人的正确年龄
# eg: A B C D E 已知E是18 求A是多少
user_list = ['A', 'B', 'C', 'D', 'E']
index = 0
def get_age():
global index
if user_list[index] == 'E':
return 18
else:
index += 1
age = get_age() + 2
return age
age = get_age()
print(age)
课外阅读
快排
def quick_sort(data):
"""快速排序"""
if len(data) >= 2: # 递归入口及出口
mid = data[len(data) // 2] # 选取基准值,也可以选取第一个或最后一个元素
left, right = [], [] # 定义基准值左右两侧的列表
data.remove(mid) # 从原始数组中移除基准值
for num in data:
if num >= mid:
right.append(num)
else:
left.append(num)
return quick_sort(left) + [mid] + quick_sort(right)
else:
return data
# 示例:
array = [2, 3, 5, 7, 21, 4, 6, 15, 25, 46, 7, 36, 10, 15, 9, 17, 19]
print(quick_sort(array))
# 输出为[2, 3, 4, 5, 6, 7, 7, 9, 10, 15, 15, 17, 19, 21, 25, 36, 46]
插入
def insertion_sort(num_list):
length = len(num_list)
if length <= 1:
return num_list
for i in range(1, length):
j = i-1 # 表示已排好序的最大索引
value = num_list[i] # 未排序列表的第一个元素
while j >= 0:
# 如果已排序的最后一个元素 < 当前未排序的元素值
if num_list[j] < value:
# 把当前未排序的元素值插入到已排序元素的最后面 退出循环
num_list[j+1] = value
break
else:
# 把已排序好元素倒叙向后移动 直到符合插入条件
num_list[j+1] = num_list[j]
# 如果当前被插入的元素一直未找到比它小的元素 则把当前元素放到首位
if j == 0:
num_list[j] = value
# 倒叙向后移动
j -= 1
print(i, num_list)
print(i, num_list)
a = [1, 3, 4, 2, 6, 9, 12, 6, 22]
insertion_sort(a)
print(a)
冒泡
lista = [34, 19, 20, 30, 10, 5, 88, 40]
for i in range(len(lista) - 1): # 交换轮次,数的个数减1
is_exchange = False # 判断是否排序完成,若排序完成不会进行交换
for j in range(len(lista) - 1): # 每一个轮次两个相邻的数都要比一遍
if lista[j] > lista[j + 1]: # 如果这个数比它后面的数大
lista[j], lista[j + 1] = lista[j + 1], lista[j] # 就交换它们的位置,后移一位
is_exchange = True
if not is_exchange:
break
print(lista)
浙公网安备 33010602011771号