1.闭包(Closure)的概念:

内部函数中对enclosing作用域的变量进行引用

  1. 1 passline = 60
  2. 2 def func(val):
  3. 3 print('%x' % id(val))
  4. 4 if val >= passline:
  5. 5 print('pass')
  6. 6 else:
  7. 7 print('faild')
  8. 8
  9. 9 def in_func():
  10. 10 print(val)
  11. 11
  12. 12 in_func()
  13. 13 return in_func
  14. 14
  15. 15 f = func(80)
  16. 16 f() #in_func
  17. 17 print(f.__closure__)

运行结果:

  1. 5d4ff910
  2. pass
  3. 80
  4. 80
  5. (<cell at 0x000001B37C8B6CD8: int object at 0x000000005D4FF910>,)

按照正常的理解,当执行完func函数后,in_func函数无法使用func函数作用域内的变量val,但是通过上面的代码,可以看到val添加到了in_func的__closure__属性中(in_func的属性__closure__对val变量进行了引用,func执行完成后val没有被释放掉),

也就是说,在函数闭包中,内部函数中对enclosing作用域的变量进行引用,并将引用变量添加到了内部函数__closure__属性中

2.装饰器

所谓装饰器,是用来装饰函数,并且返回一个函数对象

如以下求和与求平均值的两个方法:

  1. def my_sum(*args):
  2. if len(args) == 0:
  3. return 0
  4. for item in args:
  5. if not isinstance(item, int):
  6. return 0
  7. return sum(args)
  8.  
  9. def my_average(*args):
  10. if len(arg) == 0:
  11. return 0
  12. for item in args:
  13. if not isinstance(item, int):
  14. return 0
  15. return sum(args) / len(args)
  16.  
  17. print(my_sum(1,2,3))
  18. print(my_average(2,3,4,'1'))

其中,两个方法中都有相同的一段的容错处理代码:

  1. if len(arg) == 0:
  2. return 0
  3. for item in arg:
  4. if not isinstance(item, int):
  5. return 0

遵循程序设计的DRY原则,这段代码应该进行封装处理,这时便可引入函数闭包

  1. def dec(func):
  2. def in_func(*args):
  3. if len(args) == 0:
  4. return 0
  5. for item in args:
  6. if not isinstance(item, int):
  7. return 0
  8. return func(*args)
  9. return in_func
  10.  
  11. def my_sum(*args):
  12. return sum(args)
  13.  
  14. def my_average(*args):
  15. return sum(args) / len(args)
  16.  
  17. my_sum=dec(my_sum)
  18. my_average=dec(my_average)
  19.  
  20. print(my_sum(1,2,3))
  21. print(my_average(2,3,4,''))

这样就对重复的代码进行了封装。而装饰器是一种语法糖,简化了代码的编写

  1. def dec(func):
  2. print('dec called')
  3. def in_func(*args):
  4. if len(args) == 0:
  5. return 0
  6. for item in args:
  7. if not isinstance(item, int):
  8. return 0
  9. return func(*args)
  10. return in_func
  11.  
  12. @dec
  13. def my_sum(*args):
  14. print('my_sum called')
  15. return sum(args)
  16. @dec
  17. def my_average(*args):
  18. print('my_average called')
  19. return sum(args) / len(args)
  20.  
  21. # my_sum=dec(my_sum)
  22. # my_average=dec(my_average)
  23.  
  24. print(my_sum(1,2,3))
  25. print(my_average(2,3,4,''))

运行结果:

  1. dec called
  2. dec called
  3. my_sum called
  4. 6
程序执行到@dec时,调用 dec方法,返回in_dec,my_sum方法重新被赋值my_sum=in_dec(被装饰函数指向新的函数)
所以,装饰器@dec的作用就如同执行这行代码:
my_sum=dec(my_sum)

Python中闭包、装饰器的概念的更多相关文章

  1. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  2. 【Python】python中的装饰器——@

    对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...

  3. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  4. 写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...

  5. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  6. python中@property装饰器的使用

    目录 python中@property装饰器的使用 1.引出问题 2.初步改善 3.使用@property 4.解析@property 5.总结 python中@property装饰器的使用 1.引出 ...

  7. 理解Python中的装饰器

    文章先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: @makebold @makeitalic def say(): return "Hello" 打印出 ...

  8. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  9. 【Python】 闭包&装饰器

    python中的函数本身就是对象,所以可以作为参数拿来传递.同时其允许函数的层级嵌套定义,使得灵活性大大增加. 闭包 闭包的定义:将函数的语句块与其运行所需要的环境打包到一起,得到的就是闭包对象.比如 ...

  10. python函数闭包-装饰器-03

    可调用对象 callable()  # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即  callable(对象)  返回为  True  的对象 x = 1 print(cal ...

随机推荐

  1. 6.00.1x Introduction to computation

    6.00 Introduction to Computer Science                  and  Programming • Goal: –Become skillful at ...

  2. 各个浏览器开启CSS Grid Layout的方式

    2017年3月,Chrome.Firefox将开启默认支持. 当然对于很多人等不及浏览器默认支持,想提前体验一把,这里提供一些打开方式: 1.Chrome 在浏览器中输入:chrome://flags ...

  3. JSON在线解析,新版本JSON在线解析

    SOJSON,出了新版本的JSON在线解析,真的很好用,可以上下版本.左右版本.效果图如下.它的网址是:http://www.sojson.com/simple_json.html SOJSON集成了 ...

  4. 微信LazyMan笔试题的深入解析和实现

    一.题目介绍  以下是我copy自网上的面试题原文: 实现一个LazyMan,可以按照以下方式调用: LazyMan("Hank")输出: Hi! This is Hank!   ...

  5. [JQuery] Ajax使用过程中的问题总结

    JQuery提供的ajax函数,在使用过程中,因为对参数的不了解,导致了很多错误,现在总结如下,以便时常温固,不犯同样的错误. 1.我在项目中使用到的ajax请求格式如下: $.ajax({ url: ...

  6. web开发的性能准则(减少页面加载时间方面)

    准则(概述) 减少 HTTP 请求 使用CDN加速 避免空的src或href属性值 增加过期头 启GZIP压缩 把css文件放到头部 把javascript放到尾部 避免使用css表达式 删除不使用的 ...

  7. MyEclipse - 解决 MyEclipse build workspace慢,validation javascript更慢的问题

    在这个过程中对.projet文件进行了跟踪比对,总算发现这个Build的时候进行Validation是从哪里定义的了.似乎因为我的项目是基于ExtJS2.0.2的web project,所以会提示打开 ...

  8. Python学习--17 进程和线程

    线程是最小的执行单元,而进程由至少一个线程组成.如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间. 进程 fork调用 通过fork()系统调用,就可以生成一个子进程 ...

  9. Java数组练习题小结

    //2015/07/07 //Java数组小小练习题 /* 3. 写一个函数,计算一个整数数组的平均值 4. 自定义一个整数数组a,读入一个整数n,如果n 在数组中存在,则输出n 的下标:如果不存在, ...

  10. margin-top、margin-bottom的一些分析

    margin-top:表示该容器距离上面容器的距离 情况一:如果该容器上面没有容器,则这个样式属性则被父容器占用了 html代码如下: <div id ="fa"> & ...