闭包函数与装饰器

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包

闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁。

闭包示例

def config_name(name: str):
    def config_message(message):
        print(name, ':', message)

    return config_message


tom = config_name("Tom")
jerry = config_name("Jerry")

tom("你过来玩啊")
jerry("不玩")
tom("我不吃你")
jerry("谁相信")

修改外部函数变量

修改闭包内使用的外部函数变量使用 nonlocal 关键字来完成。

装饰器

装饰器就是利用了闭包函数保存外部变量的特性,比如我们可以计算函数运行的时间。

import time

def deco(func):
    def inner():
        start = time.time()
        func()
        print("函数执行时间", time.time() - start)

    return inner

@deco
def sum_num():
    result = sum([_ for _ in range(100)])
    print("100累加和:", result)

sum_num()

有参数有返回值

import time

def deco(func):
    def inner(lis):
        start = time.time()
        result = func(lis)
        print("函数执行时间", time.time() - start)
        return result

    return inner

@deco
def sum_num(lis: list):
    result = sum(lis)
    return result

lis = [_ for _ in range(100)]
result = sum_num(lis)
print(result)

通用装饰器

# 通用装饰器
def logging(fn):
  def inner(*args, **kwargs):
      print("--正在努力计算--")
      result = fn(*args, **kwargs)
      return result

  return inner

多装饰器

离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰
def make_div(func):
    """对被装饰的函数的返回值 div标签"""
    def inner(*args, **kwargs):
        return "<div>" + func() + "</div>"
    return inner


def make_p(func):
    """对被装饰的函数的返回值 p标签"""
    def inner(*args, **kwargs):
        return "<p>" + func() + "</p>"
    return inner


# 装饰过程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
@make_div
@make_p
def content():
    return "人生苦短"

result = content()

print(result)

装饰器参数

使用带有参数的装饰器,其实是在装饰器外面又包裹了一个函数,使用该函数接收参数,返回是装饰器,因为 @ 符号需要配合装饰器实例使用

# 添加输出日志的功能
def logging(flag):

    def decorator(fn):
        def inner(num1, num2):
            if flag == "+":
                print("--正在努力加法计算--")
            elif flag == "-":
                print("--正在努力减法计算--")
            result = fn(num1, num2)
            return result
        return inner

    # 返回装饰器
    return decorator


# 使用装饰器装饰函数
@logging("+")
def add(a, b):
    result = a + b
    return result


@logging("-")
def sub(a, b):
    result = a - b
    return result

result = add(1, 2)
print(result)

result = sub(1, 2)
print(result)

类装饰器

  • @Check 等价于 comment = Check(comment), 所以需要提供一个init方法,并多增加一个fn参数。
  • 要想类的实例对象能够像函数一样调用,需要在类里面使用call方法,把类的实例变成可调用对象(callable),也就是说可以像调用函数一样进行调用。
  • call方法里进行对fn函数的装饰,可以添加额外的功能。
class Check(object):
    def __init__(self, fn):
        # 初始化操作在此完成
        self.__fn = fn

    # 实现__call__方法,表示对象是一个可调用对象,可以像调用函数一样进行调用。
    def __call__(self, *args, **kwargs):
        # 添加装饰功能
        print("请先登陆...")
        self.__fn()


@Check
def comment():
    print("发表评论")


comment()

 

版权声明:
作者:hyzsj0106
链接:https://www.cxywy.com/?p=662
来源:程序员无垠
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录