我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python高级语法之闭包和装饰器详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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("发表评论")

输出结果:

–remark1----
----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()

输出:

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

到此这篇关于python高级语法之闭包和装饰器详解的文章就介绍到这了,更多相关python闭包和装饰器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python高级语法之闭包和装饰器详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python中函数总结之装饰器闭包详解

1、前言 函数也是一个对象,从而可以增加属性,使用句点来表示属性。 如果内部函数的定义包含了在外部函数中定义的对象的引用(外部对象可以是在外部函数之外),那么内部函数被称之为闭包。 2、装饰器 装饰器就是包装原来的函数,从而在不需要修改原来
2022-06-04

Python的几个高级语法概念浅析(lambda表达式闭包装饰器)

1. 匿名函数 匿名函数(anonymous function)是指未与任何标识符绑定的函数,多用在functional programming languages领域,典型应用场合: 1) 作为参数传给高阶函数(higher-order
2022-06-04

深入理解python中的闭包和装饰器

python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。 以下说明主要针对 python2.7,其他版本可能存在差异。 也许直接
2022-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录