【python基础】装饰器

codeAB 2019-12-29

一、闭包

  1、外层函数嵌套内层函数,在内层函数中使用外层函数的局部变量
  2、局部变量和内层函数统称为闭包
  3、内层函数为闭包函数

  闭包函数访问外层函数的局部变量时,访问的总是该变量的最新值

def outer():
    x = 10  # 外层函数的局部变量
    def inner():
        nonlocal x  # 关键字标记 变量x 是外层函数的局部变量
        x += 1
        return x
    return inner

r1 = outer()  # r1 --> 函数地址(内层函数)

print(r1())  # 11
print(r1())  # 12
print(r1())  # 13

r = outer()
print(r)  # <function outer.<locals>.inner at 0x0000000003C7B9D8>
print(r())  #  11 此时才是调用inner()函数的调用处

二、装饰器

  闭包的应用,对于已经实现定义好了的函数功能,在不改变原函数的情况下,给其新增功能

def outer(func):  # 外层函数的参数: 函数 --> 指的就是要装饰的函数

    def inner():
        print("此处代码在被装饰的函数执行之前执行")
        func()
        print("此处代码在被装饰的函数执行之后执行")
    return inner

@outer
def func():
    print("---嘻嘻哈哈---")

func()
"""
    此处代码在被装饰的函数执行之前执行
    ---嘻嘻哈哈---
    此处代码在被装饰的函数执行之后执行
"""
import time

def get_time(func):  # 装饰器--> 装饰的是函数

    def inner():
        before = time.time()  # 函数执行之前的时间戳
        func()
        after = time.time()  # 函数执行结束之后的时间戳
        print("函数执行时间", after - before)  # 返回值为时间戳的差值
    return inner

@get_time
def get_num():
    for x in range(100):
        print(x)

get_num()
"""
0
1
...
98
99
函数执行时间 0.0010001659393310547
"""

三、装饰一个带有返回值的函数

def outer(func):

    def inner():
        print("调用前执行")
        res = func() # 此时接收原函数的返回值
        print("调用后执行")
        return res
    return inner

@outer
def say():
    print("我是一个say函数")

say()
"""
    调用前执行
    我是一个say函数
    调用后执行
"""

@outer
def say2():
    return "我是一个say2函数"

res = say2()
# 被装饰的函数say2()--> 调用的是装饰器的inner()函数 -->  res = inner()
print(res)
"""
    调用前执行
    调用后执行
    我是一个say2函数
"""

四、装饰带有参数的函数

def outer(func):

    def inner(x):  # 形参: 被装饰的函数的形参
        print("调用前执行")
        func(x)
        print("调用后执行")
    return inner

@outer
def get_num(a):
    print(a * 10)

get_num(2)  # 被装饰后的函数 --> inner(2)
"""
    调用前执行
    20
    调用后执行
"""
def outer(func):

    def inner(*args, **kwargs):
        print("调用前执行")
        func(*args, **kwargs)
        print("调用后执行")
    return inner

@outer
def get_num(*args, **kwargs):
    print(args)
    print(kwargs)

get_num(1,2,3,4, xixi="haha", 年龄=7.5)

"""
    调用前执行
    (1, 2, 3, 4)
    {‘xixi‘: ‘haha‘, ‘年龄‘: 7.5}
    调用后执行
"""

五、多个装饰器

def outer1(func):
    def inner():
        print("装饰1调用前")
        func()
        print("装饰1调用后")
    return inner

def outer2(func):
    def inner():
        print("装饰2调用前")
        func()
        print("装饰2调用后")
    return inner

@outer2
@outer1
def study():
    print("xixihaha")

study()
"""
装饰2调用前
装饰1调用前
xixihaha
装饰1调用后
装饰2调用后
"""

六、查看被装饰函数的文档注释

  1、需要导入 from functools import wraps

  2、 装饰内层函数 @wraps(被装饰的函数)

from functools import wraps

def outer(func):
    @wraps(func)  # 解决不能查看文档注释的问题
    def inner():
        func()
    return inner

@outer
def func():
    """
    func函数
    :return: 无
    """
    print("xixi")

print(func.__doc__)
"""
    func函数
    :return: 无
"""

相关推荐