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 time模块用法实例详解
Sep 11 Python
python使用socket向客户端发送数据的方法
Apr 29 Python
Python的Django框架下管理站点的基本方法
Jul 17 Python
python基础之入门必看操作
Jul 26 Python
python中requests和https使用简单示例
Jan 18 Python
PyTorch上搭建简单神经网络实现回归和分类的示例
Apr 28 Python
python去除文件中重复的行实例
Jun 29 Python
关于Pycharm无法debug问题的总结
Jan 19 Python
python中sort和sorted排序的实例方法
Aug 26 Python
Tensorflow实现部分参数梯度更新操作
Jan 23 Python
Pytorch转keras的有效方法,以FlowNet为例讲解
May 26 Python
如何理解Python中包的引入
May 29 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
php session应用实例 登录验证
2009/03/16 PHP
Php获取金书网的书名的实现代码
2010/06/11 PHP
php生成扇形比例图实例
2013/11/06 PHP
从性能方面考虑PHP下载远程文件的3种方法
2015/12/29 PHP
laravel框架查询数据集转为数组的两种方法
2019/10/10 PHP
用Jquery实现多级下拉框无刷新的联动
2010/12/22 Javascript
Ajax 数据请求的简单分析
2011/04/05 Javascript
Prototype源码浅析 String部分(四)之补充
2012/01/16 Javascript
js禁止document element对象选中文本实现代码
2013/03/21 Javascript
jQuery Form 页面表单提交的小例子
2013/11/15 Javascript
Node.js实现Excel转JSON
2015/04/24 Javascript
javascript实现的登陆遮罩效果汇总
2015/11/09 Javascript
Bootstrap每天必学之按钮(一)
2015/11/24 Javascript
javascript设置和获取cookie的方法实例详解
2016/01/05 Javascript
详谈js中window.location.search的用法和作用
2017/02/13 Javascript
JS对象深度克隆实例分析
2017/03/16 Javascript
深入理解React高阶组件
2017/09/28 Javascript
Vue引用第三方datepicker插件无法监听datepicker输入框的值的解决
2018/01/27 Javascript
Node.js原生api搭建web服务器的方法步骤
2019/02/15 Javascript
详解async/await 异步应用的常用场景
2019/05/13 Javascript
es6函数之严格模式用法实例分析
2020/03/17 Javascript
vue实现给div绑定keyup的enter事件
2020/07/31 Javascript
JavaScript 声明私有变量的两种方式
2021/02/05 Javascript
[59:08]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第一局
2016/02/27 DOTA
使用Python的Django框架结合jQuery实现AJAX购物车页面
2016/04/11 Python
解决Django模板无法使用perms变量问题的方法
2017/09/10 Python
python实现屏保计时器的示例代码
2018/08/08 Python
python程序控制NAO机器人行走
2019/04/29 Python
Python使用itcaht库实现微信自动收发消息功能
2020/07/13 Python
pycharm 添加解释器的方法步骤
2020/08/31 Python
英国豪华文具和皮具配件经典老品牌:Smythson(斯迈森)
2018/04/19 全球购物
斯洛伐克香水和化妆品购物网站:Parfemy-Elnino.sk
2020/01/28 全球购物
银行服务明星推荐材料
2014/05/29 职场文书
社区党员公开承诺书
2014/08/30 职场文书
2016学习医德医风心得体会
2016/01/25 职场文书
JavaScript offset实现鼠标坐标获取和窗口内模块拖动
2021/05/30 Javascript