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

    闭包函数

         什么叫做函数的闭包 闭包其实就是函数的嵌套 定义在函数的内部 且内部函数用了外部函数名称空间作为名字  从而达到闭包 (函数在定义阶段的时候 他的名称空间查找顺序就已经固定的 不会因为 你的调用位置的改变而改变)

    以上就是一个闭包函数 他是先定义 outer函数 然后 a=outer()  因为这里的outer加了()号 所以 他就直接执行了函数outer 同样 它里面的函数不调用是不会执行的 最后一个返回值 inner 这个返回值他会直接给a 因为赋值了 当a加()的时候等价于 inner() 因为a的地址现在指向inner 最后执行print(name) 因为本层没有 就去上层找 发现有就执行了.

    闭包还可以这样传参   

    装饰器  

    引入问题: 定义了一个函数,想在运行时动态的增加功能,又不想改动函数本身的代码?

    装饰器其实就是一个工具 可以给其他函数添加功能 但是必须要 不能改变原函数的代码 且 不能改变函数的调用方式  开发封闭原则 对扩展开发 对修改关闭.

    如何定义一个装饰器?装饰器分为两种  第一是有参装饰器  有参就是func内可以传入参数

                        第二是无参装饰器 就是func内不可传入参数

    """假如说我们想对下面的函数添加功能但是又不能改变他的代码 和调用方式怎么办呢"""
    def login():
        print('登录成功')
    
    我们可以使用闭包来写
    
    def outer(func): #这里的func我们来传login的调用方式
        def inner(*args,**kwargs):
             #这里就可以来写他的 添加功能了 假如我们来写一个登录功能
              user_name=input('请登录:').strip()
              if user_name != '':
                    res=func(*args,**kwargs)
             return res
    return inner login=outer(login) 这里的login不是函数名 指向的地址是inner login()

    这样的一个装饰器我们就写好了   
    运行流程: 加载 login函数 加载 def outer函数
                运行outer(login)因为 ()在代码中执行权最高  里面的inner读到func 里的地址 保存下来 
    但是没有执行 然后执行return 把inner的地址返回并赋值给login 现在调用login() 就等于执行了 inner()
    然后执行里面你添加的代码 最后读到func()的时候执行 login
    因为现在的这个func指向的地址就是当初你传进来的那个 login的地址 现在加了括号就可以直接运行了.

    这段代码还可以优化 就是加装饰器语法糖@

    例如

    def outer(func):
          def inner(*args,**kwargs):
                user_name=input("输入账号").strip()
                if user_name != '':
                    res=func(*args,kwargs)
                    return res
        return inner
    
    
    @outter   这个语法糖相等于 login=outer(login) 这样你使用就可以直接调用了 不需要再写了 提升 他只会找离自己最近的那个:会将紧挨着它的可调用对象的名字当做参数自动传入调用outter
    def login (name):
           print('登录成功')
           print('欢迎',name)    

    但是他最后调用的那个login() 他的地址其实是指向 inner 因为他只是覆盖了名字 地址却没有改变 那么怎么办呢

    python自带一个 模块可以处理这个问题 装饰器修复技术 可以返回原来的函数名 返回原来函数的注释

        from functools import wraps #这个就是那个模块了 用的时候 在第二层写@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 要想装饰器不修改被装饰函数的返回值,我们需要在装饰器中接受被装饰函数的返回值并Return即可。

    2 如果希望对被装饰函数进行分类处理,我们可以在绑定装饰器时传入一个参数用于对被装饰函数进行分类,但是这样我们需要在装饰器中在套一层函数,在第一层接收装饰器传递的参数,在第二层函数中接收被装饰函数。

    3 如果希望装饰器既能装饰带参的函数也可以修饰不带参的函数,我们只需要在装饰器中接收参数时,把参数定义为非固定参数即可。

    趁自己还没死 多折腾折腾
  • 相关阅读:
    [工作中的设计模式]中介模式模式Mediator
    [工作中的设计模式]责任链模式chain
    [工作中的设计模式]迭代子模式Iterator
    [工作中的设计模式]组合模式compnent
    TI IPNC Web网页之流程分析
    TI IPNC Web网页之GoDB开发环境
    安装ubuntu时将boot目录单独挂载的意义
    ubuntu添加自定义vga输出分辨率
    GCC编译默认的头文件搜索路径
    设置搜狗输入法在任何时候按左右两侧的shift激活
  • 原文地址:https://www.cnblogs.com/lddragon/p/11177132.html
Copyright © 2011-2022 走看看