当前位置: 首页 > news >正文

python闭包与装饰器

有关闭包和装饰器的知识点的理解着实花了我不少时间,整理笔记更是无从下手,但还是将从网上搜索学习的点滴记录下来以便后期的一个补充学习。

闭包(wrapper)

闭包通俗地解释就是通过调用了函数A,函数A返回了函数B,返回的函数B就是所谓的闭包,在调用函数A的时候传递的参数就是自由变量,该自由变量是被函数A引用的,在函数A的生命周期结束后仍然存在,这句话是至今能让我比较能理解的解释。

例如:

>>>def func1(name):                             #定义一个函数func1
           def func2(age):                      #函数func2()是在func1调用的时候产生的一个闭包,且引用了自由变量name
                 print name,age
           return func2                         #函数调用完毕返回函数func2

>>> a=func1('Lily')                             #调用函数func1,且传递参数‘Lily’,将结果赋给a
>>> a(24)                                       #上一步的结果是返回函数func2,这时再将参数24赋给函数func1,调用函数func2
Lily 24

闭包不能修改外部作用域的局部变量:

>>> def a():
	x=1                                 #局部变量x的值为1
	def b():
		x=0                         #在闭包内对x的值进行重新赋值
	return x

>>> a()
1                                           #结果是x的值没有改变

使用闭包的好处呢一个就是在闭包运行之后,保存当前的运行环境,另一个是通过外部作用域的变量可以返回不同的值。

装饰器

装饰器是闭包的使用场景之一,装饰器其实也就是闭包的应用,只是区别的是装饰器传递的参数是函数。装饰器是将函数作为参数传递给一个函数,并对其进行加工处理即装饰返回一个新的函数,装饰器能保证在不改变已有的函数的结构,调用该函数返回一个新的函数,极大地提高了效率。

使用标识符@将装饰器应用在函数上,只需要在函数的定义前加上@和装饰器的名称,即@decorator

@decorator                                  #解释器将会解释成:func=decorator(func),即将函数func作为参数传递给函数decorator,然后再返回新的函数赋值给func
def func():
      pass

 多个decorator使用:

@decorator1                                 #func=decorator2(decorator1(func))
@decorator2                                 #func=decorator1(func)
def func():
     pass

 再来一个打印调用函数前log日志的无参数的装饰器例子:

>>> def log(f):
     def wrapper(*args):
           print 'call %s()' %(f.__name__)
           return f(*args)
     return wrapper

>>> @log
def func():
     print 'hello,world'

     
>>> func()
call func()
hello,world

 带参数的装饰器:

带参数的装饰器比不带参数的装饰器还要复杂一点,需要编写一个返回decorator的高阶函数

>>> def log(text):                                                   #3层嵌套的函数
	def decorator(f):                                            #返回decorator函数
		def wrapper(*args):
			print '%s %s()' %(text,f.__name__)           #将log的参数excute传递过来赋给text
			return f(*args)
		return wrapper
	return decorator                                            #先执行log('excute')函数,返回decorator函数,再调用返回wrapper函数,最后返回一个新的func函数
>>> @log('excute')
def func():
     print 'hello,world'

     
>>> func()
excute func()
hello,world
>>> 
>>> now.__name__                           #函数的name属性,通过decorator装饰器调用执行之后返回wrapper函数,所以函数名由func变成了wrapper
'wrapper'

所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写wrapper.__name__ = f.__name__这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

import functools

def log(text):
    def decorator(f):
        @functools.wraps(f)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, f.__name__))
            return f(*args, **kw)
        return wrapper
    return decorator

以上的例子都是从网上找的,比较容易理解的例子。

转载于:https://www.cnblogs.com/evablogs/p/6697219.html

相关文章:

  • PHP技能评测
  • 4月13
  • FancyBox的使用技巧 (汇总)
  • 使用Maven对JAVA程序打包-带主类、带依赖【转】
  • CSS3知识点整理一些demo
  • python loss layer: does not need backward computation?
  • [CSS] 点击事件触发的动画
  • ZooKeeper监控平台搭建
  • Problem A: 字符的变化
  • 【MongoDB学习-在.NET中的简单操作】
  • spring_restful_json_jdbc
  • Docker - 生成镜像
  • 飞鱼星路由器配置端口映射
  • 《Linux Device Drivers》第十八章 TTY驱动程序——note
  • 延迟加载JavaScript
  • 2019年如何成为全栈工程师?
  • avalon2.2的VM生成过程
  • cookie和session
  • JAVA多线程机制解析-volatilesynchronized
  • laravel 用artisan创建自己的模板
  • mysql 数据库四种事务隔离级别
  • Netty源码解析1-Buffer
  • oschina
  • Python_OOP
  • Python进阶细节
  • Python中eval与exec的使用及区别
  • vue2.0项目引入element-ui
  • vuex 学习笔记 01
  • Vue组件定义
  • Xmanager 远程桌面 CentOS 7
  • 第十八天-企业应用架构模式-基本模式
  • 二维平面内的碰撞检测【一】
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 复杂数据处理
  • 基于web的全景—— Pannellum小试
  • 前端设计模式
  • 前嗅ForeSpider采集配置界面介绍
  • 数据可视化之 Sankey 桑基图的实现
  • 微信支付JSAPI,实测!终极方案
  • 我的面试准备过程--容器(更新中)
  • 我的业余项目总结
  • 智能网联汽车信息安全
  • 《码出高效》学习笔记与书中错误记录
  • AI算硅基生命吗,为什么?
  • ​力扣解法汇总946-验证栈序列
  • (1)Android开发优化---------UI优化
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (23)Linux的软硬连接
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (LeetCode C++)盛最多水的容器
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (论文阅读40-45)图像描述1
  • (七)Knockout 创建自定义绑定
  • (区间dp) (经典例题) 石子合并