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

    一、什么是闭包函数

    1.1完整定义:

    定义在函数内部的函数,并且该函数包含对外部函数作用域的引用

    闭包函数提供了另一种为函数体传值的方式:外层函数包一个值给他

    def outter():
        x=1 # 外部传一个值给内部函数
        def inner():
            print(x)# 需要一个值
        return inner # return打破层级的限制

    二、装饰器

    2.1为什么要有装饰器?

    软件一旦上线,就应该遵守开放封闭原则:对功能升级开放,不允许修改源代码以及调用方式

    2.2装饰器的简单版本

    import time
    def my_time(): # 原本函数
        time.sleep(0.5)
        print('统计时间')
    def warpper(func):# 定义装饰器
        def inner():
            start_time=time.time()
            my_time()
            stop_time=time.time()
            print(stop_time-start_time)
        return inner
    res=warpper(my_time)
    res()

    2.3装饰器的升级版

    一、加入返回值,并支持调多个函数

    import time
    def my_time():
        time.sleep(0.5)
        print('统计时间')
        return 123 # my_time函数有返回值
    def warpper(func):
        def inner():
            start_time=time.time()
            res2=func()# 被调用的函数inner内部加返回值;并且用func来代替具体函数名,从而调用更多不同函数
            stop_time=time.time()
            print(stop_time-start_time)
            return res2 #被调用函数inner内部加return
        return inner
    my_time=warpper(my_time)
    res=my_time()
    print(res)
    my_time函数有返回值,而my_time()调用的是inner内部的函数,而他无返回值,所以要加

    二、当出现有参函数时

    import time
    def my_time(name): # 出现有参函数
        time.sleep(0.5)
        print('统计时间')
        return 123
    def warpper(func):
        def inner(*args,**kwargs): #  被调用的函数加入可变参数
            start_time=time.time()
            res2=func(*args,**kwargs) # 加入可变参数
            stop_time=time.time()
            print(stop_time-start_time)
            return res2
        return inner
    my_time=warpper(my_time)
    res=my_time('wuxi') #此处必须指定参数
    print(res)

    三、装饰器的基本形式产生

    def warpper(func):
        def inner(*args,**kwargs):
            print('此处填写要加入的功能')
            res2=func(*args,**kwargs)
            print('此处填写要加入的功能')
            return res2
        return inner

     正常我们情况下查看函数的一些信息的方法(原来的函数的函数名;原来的函数的注释)在此处都会失效。都会返回装饰函数的函数名和注释,如何使用户查看不出该函数被装饰过呢?

    采用from functools import wraps

    @warps方法

      from functools import wraps
        def outter(func):
            @wraps(func)
            def inner(*args,**kwargs):  # * **在形参中使用
                # 执行被装饰函数之前你可以做的操作
                res = func(*args,**kwargs)  # * **在实参中使用
                # 执行被装饰函数之后你可以做到操作
                return res
            return inner
    
        @outter
        def index(username,*args,**kwargs):
            """index注释"""
            pass
        print(index)
    
        装饰器修复技术
    
            1.返回原来的函数的函数名
            2.返回原来的函数的注释

    三、装饰器语法糖

    @+装饰器名。写在"装饰器"下和需要调用的函数上面。

    方便人直接调用函数

    def warpper(func):
        def inner(*args,**kwargs):
            res2=func(*args,**kwargs)
            return res2
        return inner
    @warpper #index=warpper(index) # index=inner
    def index():
        print('...')
    index()
    #@warpper 把正下方的紧挨着的函数名当做参数传入装饰器,并赋值给该函数

    现在只需直接调用index。如果index函数有返回值的话,要赋值一下再print

    多个语法糖叠加

    装饰时:从下往上
    执行时:从上往下
    @outter1#index=outter(func2)
    @outter2#func2=outter2(func1)
    @outter3#func1=outter3(index)

    有参装饰器(装饰器最复杂的版本)

    def wrappers(data):
        # data = 'file'
        def outter(func):
            def inner(*args,**kwargs):
                if data == 'file':
                    # 执行被装饰函数之前你可以做的操作
                    res = func(*args,**kwargs)  # * **在实参中使用
                    # 执行被装饰函数之后你可以做到操作
                    return res
            return inner
        return outter

    3.1现在来写一个认证装饰器

    import time
    d={
        'username':None,
    }
    def outter(func):
        def inner(*args,**kwargs):
            if d['username']:
                res = func(*args, **kwargs)
                return res
            else:
                username=input('用户名:>>>').strip()
                password=input('密码:>>>').strip()
                if username =='wuxi' and password== '123':
                    print('登录成功')
                    d['username']=True
                    res=func(*args,**kwargs)
                    return res
                else:
                    print('用户名或密码错误')
        return  inner
    @outter# inner=outter(index)
    #index=inner
    def index():
        time.sleep(0.1)
        return 1111111111111
    @outter# inner=outter(home)
    #home=inner
    def home(name):
        time.sleep(1)
        print('welcome to %s page'%name)
    res2=index()
    print(res2)
    home('wx')
  • 相关阅读:
    python 的csr_python
    OpenBLAS学习一:源码架构解析&GEMM分析
    gcc警告选项汇总
    Welcome! This is the documentation for Python 3.6.8
    CentOS 7 查看和设置防火墙状态
    django中多个app放入同一文件apps
    安装mysqlclient, 链接mysql失败,提示“Library not loaded: @rpath/libmysqlclient.21.dylib”
    动手玩转Docker(二)
    动手玩转Docker(一)
    转载:微服务部署:蓝绿部署、滚动部署、灰度发布、金丝雀发布
  • 原文地址:https://www.cnblogs.com/ZDQ1/p/11170423.html
Copyright © 2011-2022 走看看