【修仙】第一卷 初出茅庐 第十七章 装饰器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)

posted on 2022-07-06 19:12  祁珏  阅读(62)  评论(0)    收藏  举报

导航