python 闭包,装饰器以及wraps的理解和使用

一、闭包

如果在一个函数的内部定义了另外一个函数,外部的函数就叫它外函数,内部的函数就叫他内函数

闭包的条件

  • 在一个外函数中定义了一个内函数
  • 内函数里运行了外函数的临时变量
  • 并且外函数的返回值是内函数的引用

例子:

def outer(a)
    b = 10
    def inner():
        print(a+b)
    return inner


if __name__ == 'main':
    demo = outer(5)
    demo() ## 15
    

一个函数结束的时候会把自己内部的临时变量都释放了。但是闭包中,外函数发现,自己的临时变量会在将来的内部函数中被使用,所以在自己结束之后,返回内函数的同时,会把外函数的临时变量和内函数给绑定起来。所以外函数已经结束了,调用内函数的时候仍然能够使用外函数的临时变量。

补充:闭包中想要修改外函数中的变量,需要使用nonlocal 来修饰该变量然后才能对该变量进行改变

二、装饰器

先来个栗子:

import time


def showtime(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print('Running :%d s' % (end_time - start_time))

    return wrapper


@showtime
def foo1():
    print('foo1')
    time.sleep(1)


if __name__ == '__main__':
    foo1()


## 输出
foo1
Running :1 s

从上面的结果可以很清楚的了解到装饰器的原理

实际上,上面装饰器的原型为:

def showtime(func):
    def wrapper():
        print('Time start')
        start_time = time.time()
        func()
        end_time = time.time()
        print('Running %d s' % (end_time-start_time))
        print('Time end')

    return wrapper


def foo():
    print('foo..')
    time.sleep(1)


foo = showtime(foo)
foo()

带有参数的装饰器

import time


def func_argc(pre='Test'):
    def showtime(func):
        def wrapper():
            start_time = time.time()
            func()
            end_time = time.time()
            print('Running :%d s' % (end_time - start_time))
            print('pre=%s' % pre)

        return wrapper

    return showtime


@func_argc(pre='LALA')
def foo1():
    print('foo1')
    time.sleep(1)


if __name__ == '__main__':
    foo1()

# 输出
foo1
Running :1 s
pre=LALA

三、wraps

再举个栗子

def wrapper(f):
    def wrapper_function(*args, **kwargs):
        """这个是修饰函数"""
        return f(*args, **kwargs)

    return wrapper_function


@wrapper
def wrapped():
    """这个是被修饰的函数"""
    print('wrapped')


print(wrapped.__doc__)  # 输出`这个是修饰函数`
print(wrapped.__name__)  # 输出`wrapper_function`

我们发现,返回函数变成了wrapper_function。原因是给wrapped函数添加上了wrapper装饰器相当于wrapped = wrapper(wapped),而wrapper返回的函数类型为wrapper_function。

那么如果我们希望返回为当前函数自己呢?这时候就需要使用上wraps

from functools import wraps


def wrapper(f):
    @wraps(f)  # 添加上这一句话即可
    def wrapper_function(*args, **kwargs):
        """这个是修饰函数"""
        return f(*args, **kwargs)

    return wrapper_function


@wrapper
def wrapped():
    """这个是被修饰的函数"""
    print('wrapped')


print(wrapped.__doc__)  # 输出`这个是被修饰的函数`
print(wrapped.__name__)  # 输出`wrapped`

 

 

参考文献:

1. https://www.cnblogs.com/slysky/p/9777424.html

2.https://blog.csdn.net/u013380694/article/details/90019571

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值