zoukankan      html  css  js  c++  java
  • 闭包函数及装饰器

    一、闭包函数

    定义:定义在函数内部的函数引用了外部函数作用域的名字

    第一种
    def outter():
        x = 1
        def index():
            print(x)
        return index
    res = outter()
    print(res)
    res()  # 1    利用函数的返回值将函数的值打印出来
    
    
      # 首先执行定义函数outter然后执行调用函数outter,接下来执行x=1,接着执行闭包函数index,然后return返回index这个函数,就相当于一个变量名,
      #返回到outter这个调用函数,打印出的结果是index这个函数的id地址  # <function outter.<locals>.index at 0x000001F485AD0AE8>
    
    第二种
    def outter():
        x = 1
        def index():
            print(x)
        return index
    res = outter()
    
    def func():   # 如果下面在加一个函数,它的值还是为1,因为函数在定义阶已经固定,与调用位置无关
        x = 333
        res()
    func()
    View Code

    如图,此图为闭包函数的操作顺序

    给函数体传值得两种方式

    第一种:传参

     def index(username):
         print(username)  # 直接通过参数传给函数

    第二种:利用必包的形式

    def outter(x,y):
        def my_max():
            if x > y:
                return x
            return y
        return my_max
    res1 = outter(1,40)   # res1就是my_max函数的地址
    print(res1())  # 打印结果为40
    res2 = outter(20,30)
    print(res2())  # 打印结果为30
    
    # 利用闭包函数,首先在定义函数my_max里输入两个形参,
    # 然后调用函数outter里的实参值可以传入定义函数的形参中,在闭包函数中进行比较

    二、装饰器

    定义:装饰器就是给被装饰对象增加新功能的的一个工具

    开放封闭原则:通俗来讲,就是在修改一个项目的需求时,需要给它添加某个或某些功能,但是它的源代码不能更改

    装饰器必须遵循的两个原则

    1.不改变被装饰多想的源代码

    2.不改变被装饰对象(可调用对象)的调用方式

    装饰器在装饰的时候 顺序从下往上
    装饰器在执行的时候 顺序从上往下

    1.import time模块
    print(time.time())
     1562812014.731474   # 时间戳    当前时间距离1970-1-1 00:00:00相差的秒数
     1970-1-1 00:00:00是Unix诞生元年

    time.sleep(1)  # 表示让cpu停止(休息)1秒

    装饰器的简单版
    import  time
    def inner():
        time.sleep(2)
        print('您好!')
    inner()  # 会在两秒之后打印“您好!”
    
    #cpu运行的速度非常快,所以代码与代码之间运行的速度非常的快,如果中间需要读取一个文件
    # 那么可能会还没读完这个文件,就会运行下面的代码,
    #所以可以让cupc中途休息两秒,就可以读取完文件
    
    
    start = time.time()
    inner()
    end = time.time()
    print('inner run time:%s'%(end-start))   # inner run time:2.000295400619507 # inner的执行时间
    View Code

     

    2.装饰器的模板

    无参函数
    from functools import warps
    def outter(func):
      @warps(func)
        def inner(*args,**kwargs):  # 在形参中使用
            '执行被装饰函数之前你可以做得操作'
            res = func(*args,**kwargs)  # 在实参中使用
            '执行被装饰函数之后你可以做得操作'
            return res
        return inner
    
    
    有参函数
    from functools import warps
    def warppers[date]:
        date = 'file'
        def outter[func]:
        @warps(func)
            def inner[*args,**kwargs]:
                if date == 'file':
                    res = func(*args,**kwargs)
                    return res
                return inner()
        return outter
    View Code

    3.装饰器语法糖

    注意:

    语法糖在书写的时候应该与被装饰对象紧紧挨着,两者之间不能有空格

    紧挨着下面可调用对象的名字自动当做它的参数传入

    def outter(func):  # func = 最原始的index函数的内存地址
        def get_time(*args, **kwargs):
            start = time.time()
            res = func(*args, **kwargs) 
            end = time.time()
            print('func run time:%s'%(end-start))
            return res
        return get_time
    
    
    @outter  # index = outter(index)  outter(最原始的index的函数的内存地址)
    def index():
        time.sleep(3)
        print('您好!')
        return 'index
    View Code

    4.认证装饰器

    执行函数index之前,必须输入用户名和密码,正确之后才能执行index

    否则提示用户输入错误,结束程序

    def auth(func):
        # func=index
        def wrapper(*args,**kwargs):
            if current_user['username']:
                print('已经登陆过了')
                res=func(*args,**kwargs)
                return res
    
            uname=input('用户名>>: ').strip()
            pwd=input('密码>>: ').strip()
            if uname == 'egon' and pwd == '123':
                print('登陆成功')
                current_user['username']=uname
                res=func(*args,**kwargs)
                return res
            else:
                print('用户名或密码错误')
        return wrapper
    
    @auth #index=auth(index)
    def index():
        time.sleep(1)
        print('welcome to index page')
        return 122
    
    @auth
    def home(name):
        time.sleep(2)
        print('welcome %s to home page' %name)
    
    index()
    home('egon')
    View Code

    5.装饰器修复技术

    用户查看被装饰函数的函数名的时候查看到的就是被装饰函数本身
    用户查看被装饰函数的注释的时候查看到的就是被装饰函数的注释

    from functools import wraps
    def outter(func):
        @wraps(func)  # 装饰器修复技术
        def inner(*args,**kwargs):
            """
            inner函数
            :param args:
            :param kwargs:
            :return:
            """
            print('执行被装饰函数之前 你可以执行的操作')
            res = func(*args,**kwargs)
            print('执行被装饰函数之后 你可以执行的操作')
            return res
        return inner
    View Code

     5.装饰器应用场景

    1.引用日志

    2.函数执行时间统计

    3.执行函数前预备处理

    4.执行函数后清理功能

    5.权限校验

    6.缓存

  • 相关阅读:
    函数调用与参数传递总结(完成)
    序列总结
    python中如何调用.py文件
    反射获取Class对象的方式有哪些,反射创建对象的方式有哪些
    Dubbo的协议
    长连接和短连接
    hashset 和 treeset
    说说你对java中GC机制的理解
    找不着 jdbc 配置文件解决方案
    web.xml标准配置
  • 原文地址:https://www.cnblogs.com/xiongying4/p/11173520.html
Copyright © 2011-2022 走看看