• Seven-递归函数和装饰器函数


    递归函数

    递归的定义——在一个函数里再调用这个函数本身

    递归的最大深度——997

    递归函数如果不受外力的阻止就会一直执行下去,但每一次函数调用都会产生一个属于它自己的名称空间,如果一直调用下去,就会造成名称空间占用太多内存的问题,于是python为了杜绝此类现象,强制的将递归层数控制在了997

    def foo(n):
        print(n)
        n += 1
        foo(n)
    foo(1)
    测试最大递归深度

    Of course,997是python为了我们程序的内存优化所设定的一个默认值,我们还是可以通过一些方式修改默认值的

    import sys
    print(sys.setrecursionlimit(100000))
    修改递归最大深度

    不过不推荐修改默认递归深度,因为如果用997层递归都没有解决的问题不是代码太烂那就是不适合使用递归来解决

    递归示例

    我们想知道alex多大了?现只知道alex比 egon 大两岁。

    你想知道alex多大,你是不是还得去问egon?egon说,我不告诉你,但我比武sir大两岁。

    你又问武sir,武sir也不告诉你,他说他比金鑫大两岁。

    那你问金鑫,金鑫告诉你,他40了。。。

    这个时候你是不是就知道了?alex多大?

    def age(n):
        if n == 4:
            return 40
        return age(n+1)+2
    print(age(1))
    
    # 46

    二分查找算法

    定义:二分查找又称折半查找

    优点:比较次数少,查找速度快,平均性能好

    缺点:要求待查表为有序表,且执行插入删除操作困难

    因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设列表中元素是按升序排列,将列表中间位置记录的值与所需查找的值比较,如果两者相等,则查找成功;否则利用中间位置记录将列表分成前、后两个子表,如果中间位置记录的值大于需要查找的值,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,查找成功,或直到子表不存在为止,此时查找不成功

    l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
    
    def func(l,aim):
        mid = (len(l)-1)//2
        if l:
            if aim > l[mid]:
                func(l[mid+1:],aim)
            elif aim < l[mid]:
                func(l[:mid],aim)
            elif aim == l[mid]:
                print("bingo",mid)
        else:
            print('找不到')
    func(l,66)
    func(l,6)
    简单版
    def find_2(l,aim,start=0,end=None):
        if end == None:end = len(l) - 1
        if start <= end:
            mid = (end-start) // 2  + start
            if l[mid] > aim:
                find_2(l,aim,start,mid-1)
            elif l[mid] < aim:
                find_2(l,aim,mid+1,end)
            else:
                print(aim,mid)
        else:
            print('找不到这个值')
    l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
    find_2(l,32)
    
    # 32 10
    升级版

    阶乘

    def f(n):
        if n==1:
            return 1
        return n*f(n-1)
    print(f(3))
    
    # 6

    斐波那契数列

    def fib(n):
        if n==1 or n==2:
            return 1
        return fib(n-1)+fib(n-2)
    print(fib(8))
    
    # 21

    三级菜单

    menu = {
        '北京': {
            '海淀': {
                '五道口': {
                    'soho': {},
                    '网易': {},
                    'google': {}
                },
                '中关村': {
                    '爱奇艺': {},
                    '汽车之家': {},
                    'youku': {},
                },
                '上地': {
                    '百度': {},
                },
            },
            '昌平': {
                '沙河': {
                    '老男孩': {},
                    '北航': {},
                },
                '天通苑': {},
                '回龙观': {},
            },
            '朝阳': {},
            '东城': {},
        },
        '上海': {
            '闵行': {
                "人民广场": {
                    '炸鸡店': {}
                }
            },
            '闸北': {
                '火车战': {
                    '携程': {}
                }
            },
            '浦东': {},
        },
        '山东': {},
    }
    
    def menu_3(menu):
        while True:
            for key in menu:
                print(key)
            choice=input('选择:')
            if choice == 'q' or choice == 'b':
                return choice
            elif choice in menu and menu_3(menu[choice]):
                borq = menu_3(menu[choice])
                if borq == 'q':
                    return 'q'
    menu_3(menu)
    

    装饰器函数

    装饰器的本质——一个闭包函数

    装饰器的功能——在不修改原函数本身及其调用方式的前提下在原函数前后添加功能

    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner
    装饰器的固定格式
    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    装饰器的固定格式—wraps

    开放封闭原则

      对扩展是开放的

      任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何关心和修改,所以必须允许代码扩展、添加新功能

      对修改是封闭的

      我们所写的程序都是要交给用户使用的,如果我们随意对其进行修改,很有可能影响已经在使用程序的用户

    装饰器完美的遵循了这个开放封闭原则

    装饰器的形成过程

    import time
    
    def func1():
        print('in func1')
    
    def timer(func):
        def inner():
            start = time.time()
            func()
            print(time.time() - start)
        return inner
    
    func1 = timer(func1)
    func1()
    装饰器—简单版

    为了省略上面那一次赋值调用,python为我们提供了一句语法糖来解决这个问题

    import time
    def timer(func):
        def inner():
            start = time.time()
            func()
            print(time.time() - start)
        return inner
    
    @timer   #==> func1 = timer(func1)
    def func1():
        print('in func1')
    
    
    func1()
    装饰器—语法糖
    def timer(func):
        def inner(a):
            start = time.time()
            func(a)
            print(time.time() - start)
        return inner
    
    @timer
    def func1(a):
        print(a)
    
    func1(1)
    带参数的装饰器
    带参数的装饰器—other
    import time
    def timer(func):
        def inner(*args,**kwargs):
            start = time.time()
            re = func(*args,**kwargs)
            print(time.time() - start)
            return re
        return inner
    
    @timer   #==> func1 = timer(func1)
    def func1(a,b):
        print('in func1')
    
    @timer   #==> func2 = timer(func2)
    def func2(a):
        print('in func2 and get a:%s'%(a))
        return 'fun2 over'
    
    func1('aaaaaa','bbbbbb')
    print(func2('aaaaaa'))
    可以hold住所有函数传参
    import time
    def timer(func):
        def inner(*args,**kwargs):
            start = time.time()
            re = func(*args,**kwargs)
            print(time.time() - start)
            return re
        return inner
    
    @timer   #==> func2 = timer(func2)
    def func2(a):
        print('in func2 and get a:%s'%(a))
        return 'fun2 over'
    
    func2('aaaaaa','bbbbbb')
    print(func2('aaaaaa'))
    带返回值的装饰器

    正常情况下一些查看函数信息的方法都会在装饰器这里失效

    def index():
        '''这是一个主页信息'''
        print('from index')
    
    print(index.__doc__)    #查看函数注释的方法
    print(index.__name__)   #查看函数名的方法
    查看函数信息

    为了不让它们失效,需要在装饰器上加上一点来完善

    from functools import wraps
    
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    
    @deco
    def index():
        '''哈哈哈哈'''
        print('from index')
    
    print(index.__doc__)
    print(index.__name__)
    装饰器—wraps

    多个装饰器装饰同一个函数

    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner
    
    @wrapper2
    @wrapper1
    def f():
        print('in f')
    
    f()
    多个装饰器装饰同一个函数
  • 相关阅读:
    LeetCode278. 第一个错误的版本
    LeetCode275. H 指数 II
    LeetCode274. H 指数
    LeetCode273. 整数转换英文表示
    LeetCode268. 缺失数字
    LeetCode264. 丑数 II
    LeetCode263. 丑数
    关于解决Chrome新版本中cookie跨域携带和samesite的问题处理
    java将list转为树形结构的方法
    Python pycharm selenium hyrobot 学习中遇到的问题汇总2
  • 原文地址:https://www.cnblogs.com/gumo/p/7827126.html
Copyright © 2020-2023  润新知