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

    闭包函数

    闭包如何产生的?

      因为函数内部又有嵌套函数,
      嵌套函数定义:定义在内部的函数无法在全局被调用
      所以产生了闭包问题

    def func1()
        def func2()
            a = 1
            return a
        func2()

    闭包产生的问题?

      就是func1 拿不到func2 的变量a
      怎么才能拿到呢?
      我们知道,函数是第一类对象(第一类对象说白了你可以把函数当成变量使用),你可以把func1中的变量(func2)通过return返回

    def func1()
        def func2()
            a = 1
            return a
        return func2
    
    x = func1()    #这样就拿到了func2 并赋值给了变量x
    x()        # x()等同于 func2()      看明白了吧    就得到了一个返回值a   这样就拿到func2 的变量a了

    而如果:

    def func1(para1):
        para1
        def func2():
            a = 1
            return para1 + a
        return func2
    
    func1(5)    #如果把5传给func1    就会把def func2 这个函数打包,

    注意内部函数:

    def func2():
        a = 1
        return 5 + a

    func1(5)()   #等同于func2()

    就变相调用函数func2() 得到返回值 6

    print(func1(5)())   # 6

    如果func1(8), 那么func2打包后:

    def func2()
            a = 1
            return 8 + a

    每次调用func1,就会返回(打包)一个新的闭包实例

    所以:

      闭包 = 函数 + 引用环境

      闭包:python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)

    装饰器

    装饰器函数:

      装饰器函数本质 就是闭包的一种应用

      装饰器功能目的 就是实现 不修改原函数及其调用方式的情况下对原函数功能进行扩展

    def timmer(func): 
        def inner():
            print(1)
            func()          #内部函数引用外部函数的参数变量        产生闭包函数
            print(2)
        return inner
    
    def func():
        print('hello')
    
    timmer(func)  #得到 inner函数名
    f = timmer(func)    # f = inner
    f()       # inner()     
    # 1
    # hello
    # 2

    应用中涉及到的函数:

      被装饰函数
      装饰函数
      内嵌包装函数

    装饰器书写格式:

    def  wrapper(func):    ------------装饰函数
        def inner(*args,**kwargs):   ------------内嵌包装函数
            #功能添加(被装饰函数执行之前扩展的功能代码)(把这两行功能添加代码注释掉,等于去掉所有的装饰器)
            ret = func(*args,**kwargs)         
            #功能添加(被装饰函数执行之后扩展的功能代码)
            return ret
        return inner

    使用:

    @wrapper      #@wrapper 语法糖 等价于 func = wrapper(func) 
    def func():    # 被装饰函数
        return 1111    #带返回

    装饰器 开放封闭原则:

      1.对 扩展 开放 允许代码扩展、添加新功能。(修复 bug)

      2.对 修改 封闭 修改函数,有可能牵一发动全身

    小示例:一次登录,处处使用

    flag = True
    def login(args):
        def inner():
            global flag
            if flag:         #第一次调用函数,进入登录,要输入用户名和密码   如果第一次调用函数用户名密码正确,  flag为False,不用进入登录
                username = input("Please enter your user name:")
                pwd = input("Please enter your password:")
                if username == 'kitty' and pwd == '123':
                    print("Login successfully!")
                    flag = False  #用户名密码正确,就把条件改变,
            if not flag:          #如果flag发生变化,说明登录成功,否则,就进不去if语句,执行不了args()
                    args()
        return inner
    @login                      #语法糖        
    def article():
        print("Welcome to article!")
    @login
    def diary():
        print("Welcome to diary!")
    article()
    diary()
    #Please enter your user name:kitty
    # Please enter your password:123
    # Login successfully!
    # Welcome to article!
    # Welcome to diary!

    使用装饰器计算代码运行时间

    import time
    print(time.time())   #1970年1月1日00:00:00:000开始计秒
    
    def timer(func):
        def inner():
            start_time = time.time()
            time.sleep(0.1)
            func()
            end_time = time.time()
            print(end_time - start_time)
        return inner
    @timer
    def func():
        print(1111)
    func()
    View Code

    取消装饰器函数:

    def outer(flag):
        def wrapper(func):
            def inner():
                if flag:                    #falg = False   就不执行扩展功能
                    print("扩展功能")
                ret = func()
                if flag:                    ##falg = False   就不执行扩展功能
                    print("扩展功能")
                return ret
            return inner
        return wrapper
    
    @outer(False)
    #@outer(True)
    def func():
        print('kitty')
    func()

    多个装饰器装饰一个函数

    def wrapper1(func):
        def inner():
            print(111)
            func()
            print(222)
        return inner
    
    def wrapper2(func):
        def inner():
            print('aaa')
            func()
            print('bbb')
        return inner
    
    @wrapper2
    @wrapper1
    def func():
        print('kitty')
    func()
    
    aaa
    # 111
    # kitty
    # 222
    # bbb
  • 相关阅读:
    库存回滚架构设计原则
    老人血脂高吃什么好
    旁边的旁边的旁边--纪念自己逝去的青春
    JAVA8 Map新方法:compute,computeIfAbsent,putIfAbsent与put的区别
    新晋总监生存指南终章——构建技术团队信息通道
    新晋总监生存指南五——人才运营机制,技术团队如何解决造血能力
    新晋总监生存指南四——项目执行指南,如何挽救混乱的项目
    新晋总监生存指南三——OKR,先进的管理工具
    新晋总监生存指南二——建立指标
    新晋总监生存指南开篇之总监二三事
  • 原文地址:https://www.cnblogs.com/jin-yuana/p/10024639.html
Copyright © 2011-2022 走看看