python基础13 递归函数与装饰器补充

121 阅读5分钟

多层装饰器

def outter1(func1):                        # 1.定义函数outter1设置参数func1
                                           # 18.func1其实就是warpper2
    print('输出outter1')                    # 19.打印  输出哦outter1
    def wrapper1(*args, **kwargs):         # 20.定义warpper1
        print('输出wrapper1')               # 24
        res1 = func1(*args, **kwargs)      # 25  func1是warpper2,调用函数warpper2
        return res1                        # 34
    return wrapper1                        # 21.返回warpper1

def outter2(func2):                        # 2.定义函数outter2设置参数func2
                                           # 11.func2其实就是warpper3
    print('输出outter2')                    # 12.打印  输出outter2
    def wrapper2(*args, **kwargs):         # 13.定义warpper2
        print('输出wrapper2')               # 26
        res2 = func2(*args, **kwargs)      # 27 调用函数warpper3
        return res2                        # 33
    return wrapper2                        # 15.返回wrapper2

def outter3(func3):                        # 3.定义函数outter3设置参数func3
                                           # 5.func3其实就是真正的index
    print('输出outter3')                    # 6.打印   输出outter3
    def wrapper3(*args, **kwargs):         # 7.定义warpper3
        print('输出wrapper3')               # 28
        res3 = func3(*args, **kwargs)      # 29 调用index函数
        return res3                        # 32
    return wrapper3                        # 8.返回wrapper3

@outter1                # 17.outter1(warpper2)
                        # 22.接收返回值warpper1,此时函数名warpper1上面没有语法糖index=outter1(warpper2)
                        # 23.index其实是warpper1,调用函数warpper1
@outter2                # 10.outter2(warpper3)
                        # 16.接收返回值warpper2,此时函数名warpper2上面还是语法糖warpper2=outter2(warpper3)

@outter3                # 4.这一步实际是outter3(index)
                        # 9.接收返回值warpper3,此时函数名warpper3上面还是语法糖 warpper3=outter3(index)

# 语法糖的功能:会自动将下面紧挨着的函数名当作参数传递给@符号后面的函数名
                    # @outter1
                    # @outter2
                    # @outter3

def index():
    print('from index')     # 31
index()                     # 30

有参装饰器

  • 有参装饰器是为了给装饰器传递额外参数
    • 需求:在装饰器内部可以切换多种数据来源来比对用户数据
def outer(condition,type_user):
    def login_auth(func_name):                                    # 这里不能再填写其他形参
        def inner(*args, **kwargs):                               # 这里不能再填写非被装饰对象所需的参数
            username = input('username>>>:').strip()
            password = input('password>>>:').strip()
            # 应该根据用户的需求执行不同的代码
            if type_user =='jason':print('VIP')
            if condition == '列表':
                print('使用列表作为数据来源 比对用户数据')
            elif condition == '字典':
                print('使用字典作为数据来源 比对用户数据')
            elif condition == '文件':
                print('使用文件作为数据来源 比对用户数据')
            else:
                print('去你妹的 我目前只有上面几种方式')
        return inner
    return login_auth
@outer('文件','jason')
def index():
    print('from index')
index()

递归函数

  • python允许函数最大递归的调用的次数是1000次,
  • 自己验证会有所偏差在996左右,自定义最大调用次数为2000
  • 函数直接或者间接调用了自己就被称为递归调用
直接调用
def index():
    print('随便的内容')
    index()
index()

# 间接调用
def index():
    print('随便的内容')
    home()
def home():
    print('不随便的样式')
    index()
home()/index()
递归函数可用来推导一个循环有结果的事件。
递归函数每次循环都会比上一次循环简单
递归函数最终要有一个明确的结束条件

递归函数练习
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
def get_num(l1):               #1 定义函数get_num
                               #3 执行get_num内部代码
    for i in l1:               #4 for循环在l1里面的数据值
        if isinstance(i, int): #5 判断i数据值是整型,
                               # isinstance(object, classinfo)是Python中的一个内置函数,用来判断一个对象的变量类型,
                               # #object位置是实例对象,classinfo是直接或间接类名、基本类型或者由它们组成的元组

            print(i)           # 6是整型打印
        else:                  # 5判断i数据值不是整形
            get_num(i)         # 6再次调用get_num函数再次进行传值
get_num(l1)                    # 2 调用函数get_num,给函数get_num传入形参l1列表

算法:二分法

l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232]

def index(l1,target_num):                #1.定义函数index(),位置参数l1,关键字参数target_num
                                         #2.3此时相当于给l1传值了一个列表,给target_num赋值了target_num = 999

    if len(l1) == 0:                     #3.判断l1内的数据值是否为零,为零说明没有这个数。直接结束程序
        print('找不到')
        return

    middle_index = len(l1) // 2          #4.统计l1数据集的个数然后
    middle_value = l1[middle_index]      #5.获取l1列表中间的数
    if target_num > middle_value:        #6.判断进入分支
                                         # 判断大小,如果要找的数比我们得到的数大,说明要找的数在右边
        right_l1 = l1[middle_index + 1:] #6.1.对整个列表切片,得到列表判断完右边的所有数据值
                                         #   +1不包括自身顾头不顾尾"""
        print(right_l1)                  #6.2.输出获取刚才得到的切片后的列表
        index(right_l1,target_num)       #6.3.再次调用index函数给其进行传值操作

    elif target_num < middle_value:      #6.判断进入分支
                                         #  判断大小,如果要找的数比我们得到的数小,说明要找的数在左边
        left_l1 = l1[:middle_index]      #6.1对整个列表切片,得到列表判断完左边的所有数据值
                                         #  ,不用+1,最右边的数据值不包括在内。
        print(left_l1)                   #6.2输出获得刚才得到的切的列片后表
        index(left_l1,target_num)        #6.3.再次调用index函数给其进行传值操作
    else:

        print('找到了')                   #6.如果上面条件都不成立,说明要查找的数就是切分完中间的数,

index(l1,999)                            #2.1调用index函数,将l1传给被定义的函数index位置形参,
                                         #2.2 将999传给target_numc传给被定义的index的关键字行参
  • 二分法只能判断已经排好序的数据集,并且在某些查找某些开头或结尾的数值效率不高