什么是装饰器?

装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直接看示意图,其中 a 为与装饰器 @a 对应的函数, b 为装饰器修饰的函数,装饰器@a的作用是:

简而言之:@a 就是将 b 传递给 a(),并返回新的 b = a(b)

例子:

上面使用@dobi来表示装饰器,其等同于:qinfeng = dobi(qinfeng)因此装饰器本质上就是个语法糖,其作用为简化代码,以提高代码可读性,运行上段代码的结果为:

解析过程是这样子的:

1.python 解释器发现@dobi,就去调用与其对应的函数( dobi 函数)

(adsbygoogle = window.adsbygoogle || []).push({});

2.dobi 函数调用前要指定一个参数,传入的就是@dobi下面修饰的函数,也就是 qinfeng()

3.dobi() 函数执行,调用 qinfeng(),qinfeng() 打印“dobi”

什么是闭包?

首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释:

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

….

上面提到了两个关键的地方: 自由变量 和 函数, 这两个关键稍后再说。还是得在赘述下“闭包”的意思,望文知意,可以形象的把它理解为一个封闭的包裹,这个包裹就是一个函数,当然还有函数内部对应的逻辑,包裹里面的东西就是自由变量,自由变量可以在随着包裹到处游荡。当然还得有个前提,这个包裹是被创建出来的。

在通过Python的语言介绍一下,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。你在调用函数A的时候传递的参数就是自由变量。

举个例子:

def func(name): def inner_func(age): print 'name:', name, 'age:', age return inner_func bb = func('the5fire') bb(26) # >>> name: the5fire age: 26

这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收。

另外再说一点,闭包并不是Python中特有的概念,所有把函数做为一等公民的语言均有闭包的概念。不过像Java这样以class为一等公民的语言中也可以使用闭包,只是它得用类或接口来实现。

nonlocal 语句

在 python 的函数内,可以直接引用外部变量,但不能改写外部变量,因此如果在闭包中直接改写父函数的变量,就会发生错误:

在 python 2 中可以在函数内使用 global 语句,但全局变量在任何语言中都不被提倡,因为它很难控制,python 3 中引入了 nonlocal 语句解决了这个问题:

Nonlocal 与 global 的区别在于 nonlocal 语句会去搜寻本地变量与全局变量之间的变量,其会优先寻找层级关系与闭包作用域最近的外部变量。

闭包与装饰器

上面已经简单演示了装饰器的功能,事实上,装饰器就是一种的闭包的应用,只不过其传递的是函数:

@makeitalic 装饰器将函数 hello 传递给函数 makeitalic,函数 makeitalic 执行完毕后返回被包装后的 hello 函数,而这个过程其实就是通过闭包实现的。@makebold 也是如此,只不过其传递的是 @makeitalic 装饰过的 hello 函数,因此最后的执行结果<b> 在 <i> 外层,这个功能如果不用装饰器,其实就是显式的使用闭包:

闭包的作用

闭包的最大特点是可以将父函数的变量与内部函数绑定,并返回绑定变量后的函数(也即闭包),此时即便生成闭包的环境(父函数)已经释放,闭包仍然存在,这个过程很像类(父函数)生成实例(闭包),不同的是父函数只在调用时执行,执行完毕后其环境就会释放,而类则在文件执行时创建,一般程序执行完毕后作用域才释放,因此对一些需要重用的功能且不足以定义为类的行为,使用闭包会比使用类占用更少的资源,且更轻巧灵活,现举一例:假设我们仅仅想打印出各类动物的叫声,分别以类和闭包来实现:

可以看到输出结果是完全一样的,但显然类的实现相对繁琐,且这里只是想输出一下动物的叫声,定义一个 Animal 类未免小题大做,而且 voice 函数在执行完毕后,其作用域就已经释放,但 Animal 类及其实例 dog 的相应属性却一直贮存在内存中:

而这种占用对于实现该功能后,则是没有必要的。除此之外,闭包还有很多其他功能,比如用于封装等,另外,闭包有效的减少了函数参数的数目,这对并行计算非常有价值,比如可以让每台电脑负责一个函数,然后串起来,实现流水化的作业等。

python 闭包_一篇文章读懂Python的闭包与装饰器!相关推荐

  1. c 多线程运行混乱_一篇文章读懂 Python 多线程

    本文作者为 Michael Driscoll,是其新书 Python 201 的一节.本文译者为 linkcheng,由EarlGrey@编程派校对. 译者简介:linkcheng,专业电子信息工程. ...

  2. python装饰器函数执行后日志_一篇文章搞懂Python装饰器所有用法

    如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起 ...

  3. python iterable对象_一篇文章看懂 Python iterable,

    Python 中的 iterable, iterator 以及 generator,一直是非常亲密但是难以区分的概念.nvie 有一个很好的 帖子阐述了它们之间的关系,但是内容偏向于概括和总结,对于新 ...

  4. java多线程 模型_一篇文章读懂Java多线程模型

    要真正了解Java的多线程,我们还要从进程和线程的概念说起 进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期 ...

  5. python 结构体数组 定义_一篇文章弄懂Python中所有数组数据类型

    前言 数组类型是各种编程语言中基本的数组结构了,本文来盘点下Python中各种"数组"类型的实现. list tuple array.array str bytes bytearr ...

  6. bytes数组转string指定编码_一篇文章弄懂Python中所有数组数据类型

    前言 数组类型是各种编程语言中基本的数组结构了,本文来盘点下Python中各种"数组"类型的实现. list tuple array.array str bytes bytearr ...

  7. python内置模块_三分钟读懂Python内置模块collections

    collections模块 Python内置模块,在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.d ...

  8. 读懂python语言_一文读懂python反射机制

    反射 反射机制就是在运行时,动态的确定对象的类型,并可以通过字符串调用对象属性.方法.导入模块,是一种基于字符串的事件驱动.解释型语言:程序不需要编译,程序在运行时才翻译成机器语言,每执行一次都要翻译 ...

  9. axi4协议的乱序_一篇文章读懂读透FPGA AXI4 总线协议

    新一代FPGA中采用的基本都是AXI4总线协议,例如与slaver侧的DMA或DDR等通信.这篇讲AXI4的文章感觉讲的很清楚. 0.绪论AXI是高级扩展接口,在AMBA3.0中提出,AMBA4.0将 ...

最新文章

  1. 2021年大数据Spark(四):三种常见的运行模式
  2. 【pytorch】nn.conv1d的使用
  3. 在RHEL-4下半小时搭建Sendmail邮件服务器(下)
  4. Ubuntu 14.04 64bit + CUDA 6.5 配置说明
  5. Oracle学习:序列
  6. Struts2解析FreeMarker模板中变量的顺序
  7. java安全——数字签名+代码签名
  8. mysql驱动profilesql_java连接mysql的驱动配置问题
  9. 博途变量类型_PLC数据类型(UDT)
  10. 怎样在半个月内迅速提升技能,搞定面试进 大厂?
  11. bzoj3551 [ONTAK2010]Peaks加强版 kruskal重构树
  12. python中print不显示结果_Python中的print()函数
  13. 微信表情包储服务器,微信新功能!不用存图就能发出海量表情包
  14. python3哪个版本稳定-python的哪个版本稳定
  15. CISSP-安全与风险管理
  16. stm32采集交流电压信号_基于STM32的多路电压采集的设计与实现
  17. 小程序中的多表联合查询
  18. 思岚rplidar A1激光点云数据读取
  19. 数据结构与算法——深入理解红-黑树!
  20. Redisson红锁

热门文章

  1. Linux中的文件特殊权限
  2. 科学计算:Python VS. MATLAB (1)----给我一个理由先
  3. MySQL_常见函数
  4. [云炬创业基础笔记]成长资源培养与控制
  5. Scikit-Learn 与 TensorFlow 机器学习实用指南学习笔记 4 —— 数据探索与可视化、发现规律
  6. ps意外崩溃_充满意外的数学中考
  7. dcmtk程序包综述(2)
  8. RAR的命令行使用方法 收藏
  9. DOS命令大全 收藏
  10. switch判断条件