zoukankan      html  css  js  c++  java
  • python 基础 11 带参数装饰器与递归函数

    python 基础 11 带参数装饰器与递归函数

    1.递归函数

    递归函数就是在函数体里调用自己的函数。这个听着很邪乎。

    其实,说是在调用自己,其实就是在掉用函数内部的,调用自身函数命令之前的代码部分。举个例子。

    
    count = 0
    def func():
         global count
         count += 1
         print(count)
         if count == 10:return count  # 跳出机制
         #在这一层代码,调用了自己,那么就会开始执行下一个自身代码,也就是这一行之前的部分,直到符合跳出机制
         func()   
         print(456)
    func()  
    
    
    # RecursionError
    # 递归的最大深度1000层 : 为了节省内存空间,不要让用户无限使用内存空间
    # 1.递归要尽量控制次数,如果需要很多层递归才能解决问题,不适合用递归解决
    # 2.循环和递归的关系
    # 递归不是万能的
    # 递归比起循环来说更占用内存
    # 修改递归的最大深度
    # import sys
    # sys.setrecursionlimit(1000000000)
    
    # 你的递归函数 必须要停下来
    # 递归函数是怎么停下来的?递归3次结束整个函数
    # count = 0
    # def func():        # func1
    #     global count
    #     count += 1     # 1
    #     print(count)
    #     if count == 3: return
    #     func()
    #     print(456)
    # func()
    #
    # def func():        # func2
    #     global count
    #     count += 1     # 2
    #     print(count)
    #     if count == 3: return
    #     func()
    #     print(456)
    #
    #
    # def func():        # func3
    #     global count
    #     count += 1     # 3
    #     print(count)
    #     if count == 3:return
    #     func()
    #     print(456)
    
    # 函数的调用
    # 函数的参数
    # 函数的返回值
    
    # 一个递归函数要想结束,必须在函数内写一个return,并且return的条件必须是一个可达到的条件
    # 并不是函数中有return,return的结果就一定能够在调用函数的外层接收到
    # def func(count):
    #     count += 1
    #     print(count)
    #     if count == 5 : return 5
    #     ret = func(count)
    #     print(count ,':',ret)
    #     return ret
    # print('-->',func(1))
    
    # def func(1):
    #     1 += 1
    #     print(2)
    #     if 2 == 5 : return 5
    #     ret = func(2)
    #     print(ret)
    #     return ret
    #
    # def func(2):
    #     2 += 1
    #     print(3)
    #     if 3 == 5 : return 5
    #     ret = func(3)
    #     print(ret)
    #     return ret
    #
    # def func(3):
    #     3 += 1
    #     print(4)
    #     if 4 == 5 : return 5
    #     ret = func(4)
    #     print(ret)
    #     return ret
    #
    # def func(4):
    #     4 += 1
    #     print(5)
    #     if 5 == 5 : return 5
    #     func(count)
    #
    
    # def func(count):
    #     count += 1
    #     print(count)
    #     if count == 5 : return 5
    #     return func(count)
    # print('-->',func(1))
    
    
    # 递归相关 练习
    # 1.计算阶乘 100! = 100*99*98*97*96....*1
    # 循环
    # 递归
    def fin(n):
        if n == 1:
            return n
        else:
            return n*fin(n-1)
    
    
    ret = fin(7)
    print(ret)
    
    # 2.os模块:查看一个文件夹下的所有文件,这个文件夹下面还有文件夹,不能用walk
    
    def show_dir(path):
        name_list = os.listdir(path)
        for name in name_list:
            abs_path = os.path.join(path,name)
            if os.path.isfile(abs_path):
                print(name)
            elif os.path.isdir(abs_path):
                print('-->',name)
                show_dir(abs_path)
                
    # 3.os模块:计算一个文件夹下所有文件的大小.这个文件夹下面还有文件夹,不能用walk
    import os
    
    def every_file_size(path):
        sum = 0
        name_list = os.listdir(path)
        for name in name_list:
            abs_path = os.path.join(path,name)
            if os.path.isfile(abs_path):
                ret = os.path.getsize(abs_path)
                sum += ret
                print(abs_path,ret)
            elif os.path.isdir(abs_path):
                print('-->',name)
                ret = every_file_size(abs_path)
                sum += ret
        return sum
    
    s = every_file_size(r'D:programming_with_python43从零开始学python')        
    print(s)
    
    # 4.计算斐波那契数列
    # 找第100个数
    # 1 1 2 3 5
    
    def fib(num):
        if num == 1 or num == 2: return 1
        else: 
            return fib(num-2)+fib(num-1)
    fib(10)
    
    # 用循环
    def fib2(n):
        a = 1
        b = 1
        while n>2:
            a,b=b,a+b
            n -= 1
        return b
    ret = fib2(3)
    print(ret)
    
    # 由上边的循环来看,我们可以优化递归
    def fib3(n,a=1,b=1):
        if n==1 or n==2:
            return b
        else:
            a,b = b,a+b
            return fib3(n-1,a,b)
    print(fib3(100))
    
    # 或者
    # 这个方法,跟上边的这个一样,就是起点,从1=1+0开始
    def fib4(n,a=1,b=0):
        if n==1:
            return a+b
        return fib4(n-1,b,a+b)
    
    print(fib4(100))
    
    # 也可用生成器来做
    def fib5(n):
        if n==1:
            yield 1
        else:
            yield from (1,1)
            a,b=1,1
            while n>2:
                a,b = b,a+b
                yield b
                n -= 1
    a = fib5(100)
    for i in a:
        print(i)
    
    # 5.三级菜单 可能是n级
    # 递归 循环
    # https://www.cnblogs.com/Eva-J/articles/7205734.html#_label4
    menu = {
        '北京': {
            '海淀': {
                '五道口': {
                    'soho': {},
                    '网易': {},
                    'google': {}
                },
                '中关村': {
                    '爱奇艺': {},
                    '汽车之家': {},
                    'youku': {},
                },
                '上地': {
                    '百度': {},
                },
            },
            '昌平': {
                '沙河': {
                    '老男孩': {},
                    '北航': {},
                },
                '天通苑': {},
                '回龙观': {},
            },
            '朝阳': {},
            '东城': {},
        },
        '上海': {
            '闵行': {
                "人民广场": {
                    '炸鸡店': {}
                }
            },
            '闸北': {
                '火车战': {
                    '携程': {}
                }
            },
            '浦东': {},
        },
        '山东': {},
    }
    
    def menu_func(menu):
        flag = True
        while flag:
            for name in menu:
                print(name)
            key = input('想看那个城市>>>').strip()  #北京        
            if key.lower() =='q':
                print('再见')
                return False
            elif key.lower() == 'b':
                return True
            elif menu.get(key):
                flag = menu_func(menu[key])
    
    # 下边这个也对,但是我看不懂,以后再看把        
    # def menu_func(menu):
    #     while True:
    #         for name in menu:
    #             print(name)
    #         key = input('想看那个城市>>>').strip()  #北京        
    #         if key.lower() =='q':
    #             print('再见')
    #             return False
    #         elif key.lower() == 'b':
    #             return True
    #         elif menu.get(key):
    #             flag = menu_func(menu[key])
    #             if not flag: return False
    
    menu_func(menu)
    print('wahaha')
    

    2.带参数装饰器

    # 什么是装饰器?
    # 为什么要有装饰器
    # 为什么不能改变原函数的调用方式
        # 开放封闭原则
        # 我们提前写好一个功能,让别人使用的时候能够直接使用就能完成相应的功能
    
    # 登录
    # 计算函数的执行时间
    
    # 写了很多的函数
    # 添加日志 : 在 时间 调用了什么函数
    import time
    def logger(path):
        def log(func):
            def inner(*args,**kwargs):
                ret = func(*args,**kwargs)
                with open(path,mode='a',encoding='utf-8') as f:
                    msg = '%s 执行了%s'%(time.strftime('%Y-%m-%d %H:%M:%S'),func.__name__)
                    f.write(msg)
                return ret
            return inner
        return log
    
    @logger('auth.log')
    def login():
        print('登录的逻辑')
    
    @logger('auth.log')
    def register():
        print('注册的逻辑')
    
    @logger('auth.log')     # ret = log('auth.log')   show_goods = ret(show_goods)
    def show_goods():
        print('查看所有商品信息')
    
    @logger('buy.log')
    def add_goods():
        print('商品加入购物车')
    
    # 登录和注册的信息 写到auth.log文件里
    # 所有的购物信息 写到operate.log文件里
    
    login()
    add_goods()
    show_goods()
    
    # @logger('asfg')   # logger('asfg') = log
    # @log
    # @logger
    # def show_goods():
    #     print('查看所有商品信息')
    
    # def xxx(*args):
    #     def wrapper(func):
    #         def inner(*args,**kwargs):
    #             ret = func(*args,**kwargs)
    #             return ret
    #         return inner
    #     return wrapper
    
    # 原本有一个装饰器wrapper
    # @wrapper
    # def func():
    #     pass
    
    # @xxx('参数')    == @wrapper
    # def func():
    #     pass
    
    # 带参数的装饰器
    # 有100个函数,分别添加一个计算函数执行时间的装饰器
    # 有的时候需要计算时间,有的时候不需要
    # 希望能通过修改一个变量,能控制这100个函数的装饰器是否执行
    def log():
        judge = True
        if judge==True:
            def timmer(f):
                def inner(*args,**kwargs):
                    a = time.time()
                    ret = f(*args,**kwargs)
                    b = time.time()
                    print(f'{f}执行时间为{b-a}秒。')
                    return ret
                return inner
            return timmer
        else:
            pass
    
  • 相关阅读:
    Android解析聚合数据之天气预报
    (转)微信小程序开发项目——笑话大全
    如何使用优化代码段替代WordPress插件
    通用礼品卡接口文档(KFC、必胜客、GAP等)
    TP5结合聚合数据API查询天气
    移动端开发者福利-免费收费api收藏
    【小程序】微信小程序开发实践
    一个免费的API-手机号码归属地接口
    KB错误总结
    Java 视频播放
  • 原文地址:https://www.cnblogs.com/fallen043/p/12815326.html
Copyright © 2011-2022 走看看