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

    趁自己还没死 多折腾折腾
  • 相关阅读:
    Network (poj1144)
    C. Hongcow Builds A Nation
    ZYB loves Xor I(hud5269)
    D. Chloe and pleasant prizes
    Game(hdu5218)
    约瑟夫环的递推方法
    Misaki's Kiss again(hdu5175)
    Exploration(hdu5222)
    B. Arpa's weak amphitheater and Mehrdad's valuable Hoses
    C. Arpa's loud Owf and Mehrdad's evil plan
  • 原文地址:https://www.cnblogs.com/lddragon/p/11177132.html
Copyright © 2011-2022 走看看