Python闭包及装饰器运行原理解析


Posted in Python onJune 17, 2020

一、闭包

闭包从形式上来说是在外部函数中定义内部函数,并且内部函数引用了外部函数的变量,此变量叫做自由变量。

或者说是将组成函数的语句和这些语句的执行环境打包在一起。

闭包满足的条件:

必须有一个内嵌函数

内嵌函数必须使用外部函数的变量

外部函数的返回值必须是内嵌函数

def closure():
 value = []
 def fun(tmp):
  value.append(tmp)
  return value
 return fun

cc = closure() 
cc(0) #[0] 等同于closure(fun(0))
cc(1) #[0,1]
cc(2) #[0,1,2]

外部函数closure中有变量value和内部函数fun,并且内部函数fun引用了自由变量value,当执行cc = closure()时,就产生了一个闭包fun,该闭包持有只有变量value,当函数closure生命周期结束后,value依然存在,因为它被闭包引用了。

二、装饰器

装饰器其实就是闭包的应用,只不过其传递的是函数。

def add_time(fun):
 def wrapper():
  print('time: 12:00')
  return fun()
 return wrapper

def add_format(fun):
 def wrapper():
  print('\n')
  return fun()
 return wrapper

@add_format #等同于demo = add_format(add_time(demo))
@add_time #等同于 demo = add_time(demo)
def demo():
 return 'hello world!'

另外,装饰器会将demo函数的元信息丢失,例如__name__等等。

例如demo函数的__name__会由'demo'变成了'wrapper',这时需要用到functools库,在wrapper函数前加上@functools.wraps(fun):

import functools

def add_time(fun):
 @functools.wraps(fun)
 def wrapper():
  print('time: 12:00')
  return fun()
 return wrapper

def add_format(fun):
 @functools.wraps(fun)
 def wrapper():
  print('\n')
  return fun()
 return wrapper

@add_format #等同于demo = add_format(add_time(demo))
@add_time #等同于 demo = add_time(demo)
def demo():
 return 'hello world!'

例如给任意函数加上打印时间的功能的装饰器:

def metric(fn):
 start=time.time()
 @functools.wraps(fn)
 def wrapper(*args,**kw):
  end=time.time()
  print('%s executed in %s ms' % (fn.__name__,start-end))
  return fn(*args,**kw)
 return wrapper

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
用Python编写一个简单的Lisp解释器的教程
Apr 03 Python
深入理解NumPy简明教程---数组3(组合)
Dec 17 Python
Python实现简单过滤文本段的方法
May 24 Python
python中reload(module)的用法示例详解
Sep 15 Python
python中闭包Closure函数作为返回值的方法示例
Dec 17 Python
python 信息同时输出到控制台与文件的实例讲解
May 11 Python
Python对象属性自动更新操作示例
Jun 15 Python
详解python 注释、变量、类型
Aug 10 Python
Django框架模板介绍
Jan 15 Python
在python中实现同行输入/接收多个数据的示例
Jul 20 Python
python写程序统计词频的方法
Jul 29 Python
python单例设计模式实现解析
Jan 07 Python
浅谈Python协程
Jun 17 #Python
使用K.function()调试keras操作
Jun 17 #Python
哪些是python中web开发框架
Jun 17 #Python
python如何处理程序无法打开
Jun 16 #Python
python模块如何查看
Jun 16 #Python
python实现PDF中表格转化为Excel的方法
Jun 16 #Python
解决Keras 中加入lambda层无法正常载入模型问题
Jun 16 #Python
You might like
php5 non-thread-safe和thread-safe这两个版本的区别分析
2010/03/13 PHP
PHP的文件操作与算法实现的面试题示例
2015/08/10 PHP
PHP用FTP类上传文件视频等的简单实现方法
2016/09/23 PHP
PHP swoole和redis异步任务实现方法分析
2019/08/12 PHP
JS实现点击下载的小例子
2013/07/10 Javascript
利用了jquery的ajax实现二级联互动菜单
2013/12/02 Javascript
jQuery-1.9.1源码分析系列(十)事件系统之事件体系结构
2015/11/19 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
js实现简单的省市县三级联动效果实例
2016/02/18 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
js学习之----深入理解闭包
2016/11/21 Javascript
es6学习笔记之Async函数的使用示例
2017/05/11 Javascript
JS中利用FileReader实现上传图片前本地预览功能
2018/03/02 Javascript
vue项目环境变量配置的实现方法
2018/10/12 Javascript
详解Node.js 中使用 ECDSA 签名遇到的坑
2018/11/26 Javascript
Vue.js实现可排序的表格组件功能示例
2019/02/19 Javascript
JS实现压缩上传图片base64长度功能
2019/12/03 Javascript
vue 实现element-ui中的加载中状态
2020/11/11 Javascript
使用Python判断质数(素数)的简单方法讲解
2016/05/05 Python
Pycharm学习教程(3) 代码运行调试
2017/05/03 Python
django 2.0更新的10条注意事项总结
2018/01/05 Python
Python可迭代对象操作示例
2019/05/07 Python
浅析Python 条件控制语句
2020/07/15 Python
详解CSS3原生支持div铺满浏览器的方法
2018/08/30 HTML / CSS
HTML5 Canvas API中drawImage()方法的使用实例
2016/03/25 HTML / CSS
英国景点门票网站:attractiontix
2019/08/27 全球购物
Ever New美国:澳大利亚领先的女装时尚品牌
2019/11/28 全球购物
工作的心得体会
2013/12/31 职场文书
寻找最美家庭活动方案
2014/08/20 职场文书
学校师德师风自我剖析材料
2014/09/29 职场文书
文化苦旅读书笔记
2015/06/29 职场文书
教学工作总结范文5篇
2019/08/19 职场文书
Mysql中 unique列插入重复值该怎么解决呢
2021/05/26 MySQL
python中24小时制转换为12小时制的方法
2021/06/18 Python
java高级用法JNA强大的Memory和Pointer
2022/04/19 Java/Android
Redis基本数据类型Zset有序集合常用操作
2022/06/01 Redis