zoukankan      html  css  js  c++  java
  • 递归调用、高阶函数、装饰器

    一.递归调用
      递归调用: 一个函数自己调用自己, 变成一个循环了,最多一个函数递归调用自己999,作用和运行循环是一样的,区别就是循环是没有次数限制的,递归调用最多999次,超过999次会报错:
    递归的特性:
    1、 必须有一个明确的结束条件
    2、每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3、递归效率不高,少用递归
    eg:通过循环,函数自己调用自己
    def test1():
        while True:
            num = int(input('please enter a number:'))
            if num%2==0:#判断输入的数字是不是偶数
              
    return True #如果是偶数的话,程序就退出了,返回true
           
    print('不是偶数请重新输入!')
    test1() #调用test
    eg:通过递归,循环函数多次调用自己
    def test1():
        num = int(input('please enter a number:'))
        if num%2==0:#判断输入的数字是不是偶数
          
    return True #如果是偶数的话,程序就退出了,返回true
       
    print('不是偶数请重新输入!')
        return test1()#如果不是偶数的话继续调用自己,输入值
    test1()#调用test
    二.高阶函数
      高阶函数: 如果一个函数的入参是一个函数名的话,这个函数就是高阶函数
      函数即变量:虽然是一个函数,但是函数名是一个变量,变量存的是内存地址,指向的是函数体,加上括号了才是函数,那么给函数名重新赋值给一个变量的话,新变量与函数名是一样的,对新的变量名进行调用就和对原函数调用一样
    eg:函数即变量的例子
    def hello(name):
        print(name)
    new_hello=hello #hello是一个普通的变量,将hello的值赋值给new_hello,代表的是内存地址
    hello('hello...')#hello()调用hello函数
    new_hello('newhello..') #new_hello()调用的跟hello()是一样的
    eg:高阶函数的例子--入参是函数名就是高阶函数
    def add(x,y,z): 
        res=z(x)+z(y) #函数才可以用z()调用
        return res
    print(add('99','100',int))#int就是一个函数名

     

    三.装饰器

    装饰器:就是函数嵌套加高阶函数,像在打开淘宝购物的时候,哪些模块需要登录才可以操作的话,就需要用到装饰器了。
     装饰器作用,在不改变原有函数调用方式入参的情况下,给函数添加新功能,偷偷给函数加上新功能,但是不改变原来的函数
    1.  函数里可以嵌套定义函数:但是函数不管在哪都是调用了才会执行,不调用是不会执行的
    Eg:函数有内嵌函数,但是没有调用
    def warpper():
        print('我在外面')
        def deco():
            print('我在里面')
            def hh():
                print('我在最里面')
    warpper()
    返回结果:
    我在外面
    Eg:函数有内嵌函数,且有调用
    def warpper():
        print('我在外面')
        def deco():
            print('我在里面')
            def hh():
                print('我在最里面')
            hh()
        deco()
    warpper()
    返回结果:
    我在里面zhang
    VVVzhang
    2.函数作用域,是就近原则,函数里有的话就先取自己,自己没有的话,就找父级的,父级没有再往外找,查找的原则是从里往外找
    # 函数只有被调用才会执行,执行顺序按照函数调用的顺序
    Eg: 函数作用域例子
    name='luoluo'
    def warpper():
        print('我在外面%s'%name)
        def deco():
            name = 'MLing'
           
    print('我在里面%s'%name)
            def hh():
                print('我在最里面%s'%name)
            hh()
        deco()
    warpper()
    3. 装饰器:函数效率不高,查找哪个原因导致效率慢
      装饰器作用,在不改变原有函数调用方式入参的情况下,给函数添加新功能,偷偷给函数加上新功能,但是不改变原来的函数

     Eg:下面的例子获取函数的运行时间--改变原来的调用方式了 原调用方式run()---后来调用方式run_time(run)

    import time
    def run():
        print('run..')
        time.sleep(1)
    def run_time(func):
        start_time=time.time()
        func() #run传给func,func里面就是函数里的代码体,指向run函数里的两行代码
       
    end_time=time.time()
        print("run函数运行是",end_time-start_time)
    run_time(run)#run代表变量,指向的函数体里的代码,
    Eg: 下面的这个函数,其实就是就是返回了一个函数名而已deco函数没调用
    import time
    def timer(func): #定义一个函数,入参是函数名
       
    def deco(): #再定义个函数,将要给函数新加的功能写进去
           
    start_time = time.time()
            func()
            end_time = time.time()
            print("run函数运行是", end_time - start_time)
        return deco #返回这个定义的函数体
    def run():
        print('run..')
        time.sleep(1)
    timer(run) #这样调用是没有结果的,因为deco没有调用,所以timer只返回了一个deco函数名
    r=timer(run)#其实r=deco
    r()#其实就是deco(),是给原来的run函数增加了新功能之后的,但是有改变原来的调用方式,由run()变为了r()

    装饰器的处理逻辑:

    1、调用timer函数的时候,要传入一个方法名func,timer函数在函数内部定义了一个函数叫做deco
    2、deco函数内有新功能,且在函数内部调用了timer里面传入的方法-func()
    3、当调timer函数时,返回的是函数体deco,可用函数deco已经把方法-func()要实现的功能都完成了,这个直接运行deco就实现了新功能
    4、既然函数deco实现了新功能,函数即变量,给deco重新赋值就行,run=deco的话,run就有了新功能
    Eg:装饰器例子1—与上面的例子类似
    def run():
        print('run..')
        time.sleep(1)
    import time
    def run_time(func):
        def deco():
            start_time=time.time()
            func()
            end_time=time.time()
            print("run函数运行是",end_time-start_time)
        return deco#返回这个定义的函数体
    run=run_time(run)
    run()
    Eg:装饰器例子2---@run_time=run=run_time(run)
    import time
    def run_time(func):#固定格式
        def deco():#固定格式
            start_time=time.time()
            func()
            end_time=time.time()
            print("run函数运行是",end_time-start_time)
        return deco#固定格式
    @run_time #哪个函数用,就放在哪个函数前面
    def run():
        print('run..')
        time.sleep(1)
    run()
    注意:疑惑的是为什么要内嵌一个函数,就是为了不改变原来函数的调用方式,返回的是函数体,其实就是把新功能封装在了deco这个函数体里面了
    def run():
        print('run..')
        time.sleep(1)
    import time
    def run_time(func):
        def deco():
            start_time=time.time()
            func()
            end_time=time.time()
            print("run函数运行是",end_time-start_time)
        return deco
    run=run_time(run)
    print('返回的deco是什么',run)
    返回结果:
    返回的deco是什么 <function run_time.<locals>.deco at 0x000000F442D8E730>
    注意:当函数有入参的话,就需要接收传入函数的参数—下面例子是比较完美的装饰器了,有没有入参都可以
    import time,os,sys
    def timer(func):
        def deco(*args,**kwargs):
            #*args,**kwargs用来接收传入函数的参数
           
    start_time = time.time()
            res = func(*args,**kwargs)#获取返回值
           
    end_time = time.time()
            print('runtime',end_time-start_time)
            return res
        return deco
    @timer
    def run2(name):
        print(name)
        time.sleep(0.5)
    run2('niuhanyang')
     





  • 相关阅读:
    TimesTen ODBC 链接库差异及相关命令行工具的使用注意事项
    Makefile当中宏定义传递字符串
    WTL 中的常见问题汇总
    WTL 中CComboBoxEx显示不了的问题
    error C2664 转换错误汇总[转]
    LNK1123: 转换到 COFF 期间失败: 文件无效或损坏[汇总]
    python 安装mysql 客户端遇到的问题
    统计查询基本信息
    使用Log4net记录日志(非常重要)
    EntityFramework中使用sql语句
  • 原文地址:https://www.cnblogs.com/MLing/p/7020040.html
Copyright © 2011-2022 走看看