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

    一、闭包

    闭包从形式上来说是在外部函数中定义内部函数,并且内部函数引用了外部函数的变量,此变量叫做自由变量

    或者说是将组成函数的语句和这些语句的执行环境打包在一起。

    闭包满足的条件:

    • 必须有一个内嵌函数
    • 内嵌函数必须使用外部函数的变量
    • 外部函数的返回值必须是内嵌函数
    def closure():
        value = []
        def fun(tmp):
            value.append(tmp)
            return value
        return fun
    
    cc = closure() 
    cc(0) #[0] 等同于closure(fun(0))
    cc(1) #[0,1]
    cc(2) #[0,1,2]

    外部函数closure中有变量value和内部函数fun,并且内部函数fun引用了自由变量value,当执行cc = closure()时,就产生了一个闭包fun,该闭包持有只有变量value,当函数closure生命周期结束后,value依然存在,因为它被闭包引用了。

    二、装饰器

    装饰器其实就是闭包的应用,只不过其传递的是函数。

    def add_time(fun):
        def wrapper():
            print('time: 12:00')
            return fun()
        return wrapper
    
    def add_format(fun):
        def wrapper():
            print('
    ')
            return fun()
        return wrapper
    
    @add_format  #等同于demo = add_format(add_time(demo))
    @add_time  #等同于 demo = add_time(demo)
    def demo():
        return 'hello world!'

    另外,装饰器会将demo函数的元信息丢失,例如__name__等等。

    例如demo函数的__name__会由'demo'变成了'wrapper',这时需要用到functools库,在wrapper函数前加上@functools.wraps(fun)

    import functools
    
    def add_time(fun):
        @functools.wraps(fun)
        def wrapper():
            print('time: 12:00')
            return fun()
        return wrapper
    
    def add_format(fun):
        @functools.wraps(fun)
        def wrapper():
            print('
    ')
            return fun()
        return wrapper
    
    @add_format  #等同于demo = add_format(add_time(demo))
    @add_time  #等同于 demo = add_time(demo)
    def demo():
        return 'hello world!'

    例如给任意函数加上打印时间的功能的装饰器:

    def metric(fn):
        start=time.time()
        @functools.wraps(fn)
        def wrapper(*args,**kw):
           end=time.time()
           print('%s executed in %s ms' % (fn.__name__,start-end))
           return fn(*args,**kw)
        return wrapper
  • 相关阅读:
    自愿如此 四 内观
    自愿如此· 三 不做解释
    自愿如此·序言
    排序算法 (08.堆排序)
    2.2 ES6 解构赋值
    2.1 ES6 let 与 const
    ES6学习 (01. 内容概况)
    vue 技术栈进阶 (07. ajax 请求实战)
    vue技术栈进阶(06.状态持久化, 严格模式, 数据双向绑定问题)
    vue技术栈进阶(05. mutations, actions)
  • 原文地址:https://www.cnblogs.com/LMIx/p/13126617.html
Copyright © 2011-2022 走看看