python闭包和装饰器如何理解,怎样使用?

Admin 2021-05-31 群英技术资讯 888 次浏览

       对一些新手来说python闭包和装饰器是比较难理解的内容,为帮助大家更好的理解和学习python闭包和装饰器,下面给大家介绍一些关于python闭包和装饰器的实例,需要的朋友可以参考学习。

       一、闭包

       闭包的形成条件:

       1.函数嵌套。

       2.内部函数使用了外部函数的变量或者参数。

       3.外部函数返回了使用外 部变量的内部函数。

       二、一个简单的例子

def func_out(num1):
    def inner(num2):
        res = num1 + num2
        print(res)
    return inner
# a = func_out(10)(10)
a = func_out(10)
a(10) 

       闭包修改外部函数的变量:

       在闭包内修改外部函数的变量需要使用nonlocal关键字

def func_out():
    # 外部函数的变量
    num1 = 10
    def func_inner():
        # 在闭包内修改外部函数的变量
        nonlocal num1
        num1 = 20
        res = num1 +20
        print(res)
    print("修改前的变量", num1)
    func_inner()
    print("修改后的变量", num1)
    return func_inner
new_func = func_out()
new_func() 

       三、装饰器

       3.1 简单装饰器

       装饰器就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数,也就是说也是一个函数嵌套。装饰器的功能特点:

       1.不修改已有函数的源代码

       2.不修改已有函数的调用方式

       3.给已有函数增加额外的功能

       用户在发表评论的时候需要验证用户是否登录,我们首先会想到去修改原来的函数,在函数里面添加一些功能,但是在现在这分工合作的时代,这样的修改很容易出现修改了祖传的代码后,函数出现问题,也影响代码的高效复用。为了能够不重新修改原来的评论的代码,实现高水平的代码复用。

       原本的函数及其调用:

def comment():
    print("执行祖传代码.....")
    print("发表评论")
# 调用评论功能
comment()

       自己手写一个实现装饰器功能的函数实现登录验证:

def decorator(func):
    def inner():
        print('正在验证登录者身份...\n验证成功')
        func()
    return inner


def comment():
    print("执行祖传代码.....")
    print("发表评论")
# 调用评论功能
comment = decorator(comment)
comment() 

       输入结果:

正在验证登录者身份…
验证成功
执行祖传代码…
发表评论

       3.1.1 使用装饰器的语法糖

       装饰器的语法糖写法:@装饰器名称

       如例子可以改写为:

def decorator(func):
    def inner():
        print('正在验证登录者身份...\n验证成功')
        func()
    return inner

@decorator
def comment():
    print("执行祖传代码.....")
    print("发表评论")

# 调用函数
comment() 

       运行结果:

正在验证登录者身份…
验证成功
执行祖传代码…
发表评论

       3.1.2 装饰器的执行时机

       先说结论:在使用装饰器语法糖时,会先将该装饰器函数执行一遍。

def decorator(func):
    # 测试装饰器的执行时机
    print('--remark1----')
    def inner():
        print('正在验证登录者身份...\n验证成功')
        func()
    print('----remark2---')
    return inner

@decorator
def comment():
    print("执行祖传代码.....")
    print("发表评论") 

       输出结果:

--Cremark1----
----remark2―

       3.2 通用装饰器

       装饰的函数可能有参数传递,或者有返回值,上面写的例子中,如果依然用上面的方法及逆行装饰器的装饰将会出现问题,那是否有一个通用的装饰器能够装饰任意函数呢?

       3.2.1 装饰带有参数的函数

def logging(fn):
    def inner(num1,num2):
        print('执行了一次计算')
        fn(num1,num2)
    return inner
# 使用装饰器装饰函数
@logging
def sum_num(a,b):
    result = a + b
    print(result)
    
sum_num(1,2) 

       3.2.2. 装饰带有返回值的函数:

def logging(fn):
    def inner(num1,num2):
        print('执行了一次计算')
        result = fn(num1,num2)
        return result
    
    return inner
# 使用装饰器装饰函数
@logging
def sum_num(a,b):
    result = a + b
    return result
    
print(sum_num(1,2)) 

       3.2.3 实现通用装饰器

*args: 用于接收元组参数,可传可不传

**kwargs: 用于接收字典类型参数,可传可不传

def logging(fn):
    def inner(*args, **kwargs):
        result = fn(*args, **kwargs)
        return result
    return inner

@logging
def sum_num(a,b):
    result = a + b
    return result 

       3.3 多个装饰器的使用

       多个装饰器的过程:由内到外的装饰过程,先执行内部装饰器,再执行外部装饰器。

       原理剖析:content = make_div(make_p(content))

       分步拆解:content = make_p(content), 内部装饰器完成content=make_p.inner, content = make_div(make_p.inner)

def make_div(func):
    print("make_div装饰器执行了")
    def inner():
        # 在内部函数对已有函数进行装饰
        result = "<div>" + func() +"</div>"
        return result
    return inner

def make_p(func):
    print("make_p装饰器执行了")
    def inner():
        # 在内部函数对已有函数进行装饰
        result = "<p>" + func() +"</p>"
        return result
    return inner

@make_div
@make_p
def content():
    return "人生苦短,我用Python" 

       输出:

make_p装饰器执行了
make_div装饰器执行了
<div><p>人生苦短,我用Python</p></div>

       3.4 带有参数的装饰器

       带有参数的装饰器时机上就是定义了一个函数,让函数接收参数,再函数内部返回该装饰器。

       如定义一个能够判断加减的装饰器:

def return_decorator(flag):
    def decorator(func):
        def inner(a,b):
            if flag == '+':
                print("正在进行加法运算")
            elif flag == '-':
                print("正在进行减法运算")
            func(a,b)
        return inner
    return decorator
@return_decorator('+')
def add_num(a,b):
    print(a+b)

add_num(1,5) 

       3.5 类装饰器

       使用类装饰已有函数。

class MyDecorator(object):
    def __init__(self,func):
        self.__func = func
    # 实现__call__方法,让对象变成可调用的对象,
    # 可调用的对象能够像函数一样被使用。
    def __call__(self,*args,**kwargs):
        # 对已有参数进行封装
        print('--正在进行装饰-----')
        self.__func()
        
@MyDecorator
def show():
    print("hello")

# 指向MyDecorator类创建实例对象--> show()==> 对象()
show() 

       输出:

--C正在进行装饰-----
hello

       关于python闭包和装饰器的相关内容就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果想要了解更多python闭包和装饰器,大家可以关注其他相关文章。

文本转载自脚本之家

群英智防CDN,智能加速解决方案

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

猜你喜欢

成为群英会员,开启智能安全云计算之旅

立即注册
专业资深工程师驻守
7X24小时快速响应
一站式无忧技术支持
免费备案服务
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
在线客服
微信公众号
返回顶部
返回顶部 返回顶部
在线客服
在线客服