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实现简单的邮件发送客户端示例
Dec 23 Python
python实现数独游戏 java简单实现数独游戏
Mar 30 Python
Python实现的knn算法示例
Jun 14 Python
python之cv2与图像的载入、显示和保存实例
Dec 05 Python
基于python实现百度翻译功能
May 09 Python
python里运用私有属性和方法总结
Jul 08 Python
python 接口实现 供第三方调用的例子
Aug 13 Python
wxpython实现按钮切换界面的方法
Nov 19 Python
Python使用Selenium实现淘宝抢单的流程分析
Jun 23 Python
Python读取图像并显示灰度图的实现
Dec 01 Python
Python实现简单的猜单词
Jun 15 Python
python中Matplotlib绘制直线的实例代码
Jul 04 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
国产动画《伍六七》原声大碟大卖,啊哈娱乐引领音乐赋能IP的新尝试
2020/03/08 国漫
php 随机生成10位字符代码
2009/03/26 PHP
php数组排序usort、uksort与sort函数用法
2014/11/17 PHP
PHP各种异常和错误的拦截方法及发生致命错误时进行报警
2016/01/19 PHP
PHP检测用户是否关闭浏览器的方法
2016/02/14 PHP
Yii针对添加行的增删改查操作示例
2016/10/18 PHP
php判断str字符串是否是xml格式数据的方法示例
2017/07/26 PHP
Laravel创建数据库表结构的例子
2019/10/09 PHP
PHP实现微信公众号验证Token的示例代码
2019/12/16 PHP
jQuery 各种浏览器下获得日期区别
2008/12/22 Javascript
判断用户的在线状态 onbeforeunload事件
2011/03/05 Javascript
JQuery的$和其它JS发生冲突的快速解决方法
2014/01/24 Javascript
jQuery左右滚动支持图片放大缩略图图片轮播代码分享
2015/08/26 Javascript
深入分析Javascript事件代理
2016/01/30 Javascript
浅析BootStrap模态框的使用(经典)
2016/04/29 Javascript
AngularJS表达式讲解及示例代码
2016/08/16 Javascript
AngularJS递归指令实现Tree View效果示例
2016/11/07 Javascript
5种JavaScript脚本加载的方式
2017/01/16 Javascript
jQuery代码优化方法总结
2018/01/29 jQuery
VUE 配置vue-devtools调试工具及安装方法
2018/09/30 Javascript
纯js实现无缝滚动功能代码实例
2020/02/21 Javascript
JS实现简易图片自动轮播
2020/10/16 Javascript
python出现"IndentationError: unexpected indent"错误解决办法
2017/10/15 Python
Python之修改图片像素值的方法
2019/07/03 Python
tensor和numpy的互相转换的实现示例
2019/08/02 Python
在python中利用try..except来代替if..else的用法
2019/12/19 Python
Django 再谈一谈json序列化
2020/03/16 Python
HTML5在IE10、火狐下中文乱码问题的解决方法
2013/11/18 HTML / CSS
巧克力领导品牌瑞士莲美国官网:Lindt Chocolate美国
2016/08/25 全球购物
纽约手袋品牌:KARA
2018/03/18 全球购物
单位办理社保介绍信
2014/01/10 职场文书
《散步》教学反思
2014/03/02 职场文书
2014年大学生党员自我评议
2014/09/22 职场文书
2019年公司快递收发管理制度模板
2019/11/20 职场文书
Python+Appium实现自动抢微信红包
2021/05/21 Python
OpenFeign实现远程调用
2022/08/14 Java/Android