美文网首页
闭包、装饰器

闭包、装饰器

作者: xiaohan_zhang | 来源:发表于2019-07-20 16:18 被阅读0次

闭包

在函数嵌套的前提下,内部函数使用了外部函数的变量,把这个内部函数成为闭包。

  • 闭包构成条件
    1.1 函数嵌套(函数里面再定义函数)
    1.2 内部函数使用外部函数的变量
    1.3 外部函数返回了内部函数
def func_out1():
    num1 = 10
    def func_inner(num2):
        result = num1 + num2
        print(f'result = {result}')
    return func_inner


# 闭包保存了外部函数的变量num1,执行闭包都是在num1 = 10的基础上进行计算。
func_out1()(2)  # result = 13
f = func_out1()
f(3)    # result = 14


def func_out2(num1):
    def func_inner(num2):
        result = num1 + num2
        print(f'result = {result}')
    return func_inner


f = func_out2(1)
f(1)    # result = 2
  • 修改外部函数中的变量
    python3: nonlocal修饰
def func_out3(num1):
    def func_inner():
        # 在闭包内修改外部函数变量,需要使用nonlocal关键字修饰
        nonlocal num1
        num1 += 1

    print(f'修改前:num1 = {num1}')
    func_inner()
    print(f'修改后:num1 = {num1}')
    return func_inner


func_out3(1)()


def func_out4(num1):
    def func_inner():
        nonlocal num1
        num1 += 1
        return num1

    return func_inner


f = func_out4(10)
print(f())  # 11

装饰器

装饰器本质是一个闭包函数,可以对已有函数进行额外的功能扩展。
装饰器执行时机:
当前模块加载完成时,装饰器会立即执行,对已有函数进行装饰

  • 装饰器(decorator)功能
  1. 不修改已有函数的源代码
  2. 不修改已有函数的调用方式
  3. 给已有函数增加额外功能
  • 装饰器语法格式
def decorator(func):    # func被装饰的目标函数
    def inner():
        '''执行函数之前'''
        func()      # 执行被装饰的目标函数
        '''执行函数之后'''
    return inner
# 装饰器语法糖用法:
@装饰器名称 修饰被装饰函数
  • 装饰器示例
    1. 装饰无参数的函数
# 如果闭包函数有且只有一个参数,并且是函数类型,那么这个闭包函数称为装饰器
def outter(func):
    def inner():
        print("登录验证")
        func()
    return inner

# 装饰器语法糖写法 等价于comment = outter(comment)
@outter
def comment():
    print("发表评论")


comment()
# 调用装饰器对已有函数进行装饰
# comment = outter(comment)
# comment()
"""
登录验证
发表评论
"""
  1. 装饰有参数的函数
def decorator_add(func):
    def inner(num1, num2):
        print('正在努力执行加法运算....')
        func(num1, num2)
    return inner


@decorator_add
def add_num(num1, num2):
    result = num1 + num2
    print(f'结果为:{result}')


add_num(1, 4)
"""
正在努力执行加法运算....
结果为:5
"""
  1. 装饰器带有返回值的函数
def decorator_add2(func):
    def inner(num1, num2):
        print('2正在努力执行加法运算....')
        return func(num1, num2)
    return inner

@decorator_add2
def add_num2(num1, num2):
    return num1 + num2


result = add_num2(1, 2)
print(f'有返回值函数:result = {result}')
'''
正在努力执行加法运算....
有返回值函数:result = 3
'''
  1. 装饰带有不定长参数的函数
def decorator_add3(func):
    def inner(*args, **kwargs):
        print('3正在努力执行加法运算....')
        return func(*args, **kwargs)    # 拆包
    return inner

@decorator_add3
def add_num3(*args, **kwargs):
    print("-----call_func:args =", args, ",kwargs =", kwargs)
    result = 0
    for value in args:
        result += value
    for value in kwargs.values():
        result += value
    return result


result = add_num3(1, 3)
print(f'不定长参数函数:result = {result}')
result = add_num3(1, 3, num=4)
print(f'不定长参数函数:result = {result}')
'''
3正在努力执行加法运算....
-----call_func:args = (1, 3) ,kwargs = {}
不定长参数函数:result = 4
3正在努力执行加法运算....
-----call_func:args = (1, 3) ,kwargs = {'num': 4}
不定长参数函数:result = 8
'''
  1. 通用装饰器
def decorator(func):
    def inner(*arg, **kwargs):
        print('通用装饰器')
        res = func(*arg, **kwargs)
        return res
    return inner


@decorator
def show():
    print('哈哈哈哈哈哈')


show()
  1. 多个装饰器对同一个函数装饰
"""
多个装饰器的执行过程:
由内到外装饰,先执行内部装饰器,再执行外部装饰器
"""
def make_p(func):
    print('make_p装饰器执行了')
    def inner():
        content = '<p>' + func() + '</p>'
        return content
    return inner

def make_div(func):
    print('make_div装饰器执行了')
    def inner():
        content = '<div>' + func() + '</div>'
        return content
    return inner

@make_div
@make_p
def content():
    return "装饰器使用练习"


print(content())
"""
make_p装饰器执行了
make_div装饰器执行了
<div><p>装饰器使用练习</p></div>
"""
  1. 带有参数的装饰器
    带有参数的装饰器就是使用装饰器的时候,可以传入指定参数;
    语法格式:@装饰器(参数...)
    带有参数的装饰器其实就是在装饰器外面又包了一层函数,使用该函数接收参数,返回装饰器。
def return_decorator(flag):
    def decorator(func):
        def inner(num1, num2):
            if flag == '+':
                print('正在努力执行加法运算')
            elif flag == '-':
                print('正在努力执行减法运算')
            func(num1, num2)
        return inner
    return decorator

@return_decorator('+')
def add_num(a, b):
    res = a + b
    print(res)

@return_decorator('-')
def sub_num(a, b):
    res = a - b
    print(res)


add_num(2, 5)
sub_num(5, 2)
'''
正在努力执行加法运算
7
正在努力执行减法运算
3
'''
  1. 类装饰器
class Check(object):
    def __init__(self, func):
        self._func = func

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

@Check
def show():
    print('快要下雪了')


show()
'''
添加装饰功能
快要下雪了
'''

  • 装饰器使用场景
    1. 引入日志
    2. 函数执行时间统计
    3. 执行函数前预备处理
    4. 执行函数后清理功能
    5. 权限校验等场景
    6. 缓存

相关文章

  • python 高级 13闭包 装饰器

    闭包和装饰器 1.8 闭包和装饰器 学习目标 1. 能够说出闭包的定义形式 2. 能够说出装饰器的实现形式 ...

  • Python的自定义超时机制——装饰器的妙用

    装饰器 关于装饰器的入门,可以参考这篇文章:12步轻松搞定python装饰器简单来说,装饰器其实就是一个闭包(闭包...

  • Python装饰器-专题笔记

    学会装饰器,Python更进阶 函数作用域到闭包到装饰器讲解,及闭包和装饰器的运用。 [√] 慕课网Meshare...

  • Python-闭包和修饰器

    作用域 闭包 code: 装饰器 code: 装饰器案例 code:

  • Python 2 - 高级用法 - 装饰器

    Python 2 - 高级用法 - 装饰器 一谈到 装饰器,就离不开闭包 闭包 闭包就是能够读取其他函数内部变量的...

  • 装饰器

    1.装饰器的概念 装饰器是一个闭包:内层函数引用外层函数的变量(参数也算变量),然后返回内层函数,就是闭包。装饰器...

  • Python装饰器——初识

    上次讲了Python的闭包,今天来讲一下闭包的应用——装饰器 1. 装饰器是什么 什么叫装饰器?顾名思义,它是一个...

  • chapter7 函数式编程

    闭包 匿名函数 装饰器 偏函数

  • python装饰器

    学习了闭包的概念之后,再来学习装饰器就简单很多。装饰器就是闭包的一个应用 代码举例 但是装饰器在使用时分加载态和调...

  • [python] 装饰器学习

    很多python的代码都带有装饰器=。=现在不学以后也要学学一下装饰器 闭包 在学装饰器之前先看看python的闭...

网友评论

      本文标题:闭包、装饰器

      本文链接:https://www.haomeiwen.com/subject/kpdylctx.html