有参装饰器与递归函数

本章内容

  • 多层语法糖内部本质
  • 有参装饰器
  • 递归函数
  • 算法之二分法

多层语法糖内部本质

"""语法糖会将紧挨着的被装饰对象的名字当做参数自动传入装饰器函数中"""
# 示例:
#判断七句print的执行顺序
def func1(func_name):
    print('执行func1')
    def inner(*args, **kwargs):
        print('输出func1')
        res = func_name(*args, **kwargs)
        return res
    return inner
def func2(func_name):
    print('执行func2')
    def inner(*args, **kwargs):
        print('输出func2')
        res = func_name(*args, **kwargs)
        return res
    return inner
def func3(func_name):
    print('执行func3')
    def inner(*args, **kwargs):
        print('输出func3')
        res = func_name(*args, **kwargs)
        return res
    return inner
@func1
@func2
@func3 # index = func3(index)
def index():
    return '这是原函数'
res = index()
print(res)   
image-20220321164128154

有参装饰器

def outer(source_data):
    def login_auth(func_name):  # 不能动  只能接收一个被装饰对象名字
        def inner(*args, **kwargs):  # 不能动 是专门用来给被装饰的对象传参的
            username = input('username>>>:').strip()
            password = input('password>>>:').strip()
            # 校验用户数据  数据的来源可以有很多 比如全局字典 全局列表 文本文件 数据库
            # 数据的来源不同 处理方式就不同 对应的代码编写就不一样
            # 分支结构处理 然后根据不同的参数提示 匹配不同的流程
            if source_data == '1':
                print('使用字典的方式处理数据')
            elif source_data == '2':
                print('使用列表的方式处理数据')
            elif source_data == '3':
                print('使用文件操作处理数据')
            else:
                print('其他操作情况')
            res = func_name(*args, **kwargs)
            return res
        return inner
    return login_auth
"""
函数名加括号 执行优先级最高

@outer('3')
    左侧是语法糖结构 右侧是函数名加括号结构   
        先执行函数调用  outer('3')  返回值是login_auth
        在执行语法糖结构  @login_auth
    发现最后还是一个普通的装饰器
有参装饰器目的仅仅是给装饰器传递额外的参数  
    装饰器最多就三层嵌套
并且三层嵌套的结构使用频率不高(最多是使用别人写好的有参装饰器)
    from functools import wraps
    @wraps(func_name)
"""

@outer('3')
def index():
    print('from index')
image-20220321170644942

递归函数

# 本质:递归函数也称为函数的递归
	函数在运行过程中直接或者间接的调用了自身
 
# 基本演示
# 直接调用自己
# def index():
#     print('from index')
#     index()
# index()
"""
maximum recursion depth exceeded while calling a Python object
最大递归深度超出限制了     python解释器自带的应急机制

在有些编程语言中 甚至没有遇警机制 代码执行真的一致到计算机崩溃为止
"""
# 间接调用自己
# def index():
#     print('from index')
#     func()
# def func():
#     print('from func')
#     index()
# func()
"""
maximum recursion depth exceeded while calling a Python object
    这对python最大递归深度
        回答997 998 1000都可以
    官方给出的是1000
"""
# import sys
# print(sys.getrecursionlimit())  # 获取默认的最大递归深度  # 1000
# sys.setrecursionlimit(2000)  # 还可以修改最大递归深度
# count = 1
# def index():
#     print('from index')
#     global count
#     print(count)
#     count += 1
#     index()
# index()

"""
函数的递归不应该是无限循环的过程 真正的递归函数应该要满足两个要求
    1.每次递归 复杂度必须降低(下一次递归要比上一次递归解答)
        大白话 越往下递归应该离解决问题的答案越近
    2.必须要有明确的结束条件
"""

	
# 诠释
"""
需求:我想知道我们班坐在第一排的某个学生年龄
过程:
    我问他多大了 他调皮不告诉我 说比后面那个同学大两岁
    后面的说比他后面的大两岁
    ...
    问到最后你一排 终于开口说 18岁
    ...
    知道最后一排的年级回推就可以知道第一排的年级
名词:
    递推:一层层往下问
    回溯:根据结果推结论
"""
# 如何编写代码完成
    # 目标人物的年龄 = 后一排年龄 + 2
    # 后一排年龄 = 后后一排年龄 + 2
    # 后后一排年龄 = 后后后一排年龄 + 2
    # 后后后后一排年龄 = 18
# 将求问年龄变成函数
    # 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(4))
'''千万不要想复杂了 就记嵌套图即可 有结果就是由内而外一层层拨开'''
image-20220321170744079

算法之二分法

# 什么是算法?
	算法其实就是解决问题的有效方法
  	eg:比如打开易拉罐的问题
      	方法1:使用金属撬棍
        方法2:直接手扣
        方法3:一阳指戳
        ...
  """
  算法比较偏向于学术研究 很枯燥 并且产出很少
  甚至只有非常大的互联网公司才会有算法部分
  	算法工程师薪资待遇很高 但是产出很少
  	有时候甚至几年都没有任何的成果 有点类似于研究所!!!
  """

# 算法之二分法
	二分法是算法里面最入门的一个 主要是感受算法的魅力所在
  # Author:Jason
"""二分法使用有前提: 数据集必须有先后顺序(升序 降序)"""
l1 = [13,21,35,46,52,67,76,87,99,123,213,321,432,564,612]
# 查找一个数 123
"""
二分法原理
    获取数据集中间的元素 比对大小
        如果中间的元素大于目标数据  那么保留数据集的左边一半
        如果中间的元素小于目标数据  那么保留数据集的右边一半
    然后针对剩下的数据集再二分
        如果中间的元素大于目标数据  那么保留数据集的左边一半
        如果中间的元素小于目标数据  那么保留数据集的右边一半
    ...
"""
def get_target(l1,target_num):
    # 最后需要考虑找不到的情况 l1不可能无限制二分
    if len(l1) == 0:
        print('不好意思 真的没有 找不到')
        return
    # 1.获取中间元素的索引值(只能是整数)
    middle_index = len(l1) // 2
    # 2.判断中间索引对应的数据与目标数据的大小
    if target_num > l1[middle_index]:
        # 3.保留数据集右侧
        l1_left = l1[middle_index+1:]
        # 3.1.对右侧继续二分 重复执行相同代码 并且复杂度降低
        print(l1_left)
        get_target(l1_left,target_num)
    elif target_num < l1[middle_index]:
        # 4.保留数据集左侧
        l1_right = l1[:middle_index]
        print(l1_right)
        # 4.1.对右侧继续二分 重复执行相同代码 并且复杂度降低
        get_target(l1_right,target_num)
    else:
        print('找到了',target_num)
# get_target(l1,432)
# get_target(l1,22)
get_target(l1,13)
"""
二分法的缺陷
    1.如果要找的元素就在数据集的开头 二分更加复杂
    2.数据集必须有顺序
目前没有最完美的算法 都有相应的限制条件
"""
"""
以后面试的时候  可能会让你手用python写一些算法
    二分法 快排 插入 冒泡 堆排序
        上述知识面试之前临时抱佛脚即可 平时无需过多研究
"""
image-20220321171347705
posted @   DDYT  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示