闭包(closure)是函数式编程的重要的语法结构。

  定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).

  1. def outer():
  2. x = 1
  3. def inner():
  4. print(x)
  5. return inner
  6. f = outer()
  7. f()

inner就是内部函数,inner里引用了外部作用域的变量x(x在外部作用域outer里面,不是全局作用域),则这个内部函数inner就是一个闭包。

闭包=函数块+定义函数时的环境,inner就是函数块,x就是环境。

装饰器

  装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。

  它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

简单的装饰器函数:

@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作

  1. import time
  2. def shoe_time(f):
  3. def inner():
  4. start = time.time()
  5. f()
  6. end = time.time()
  7. print(end-start)
  8. return inner
  9. @shoe_time #foo = shoe_time(foo)
  10. def foo():
  11. #start = time.time()
  12. print("foo......")
  13. time.sleep(2)
  14. #end = time.time()
  15. #print(end-start) #2.0001144409179688
  16. #foo()
  17. @shoe_time #bar = shoe_time(bar)
  18. def bar():
  19. # start = time.time()
  20. print("bar......")
  21. time.sleep(3)
  22. #end = time.time()
  23. #print(end-start) #3.001171588897705
  24. #bar()
  25. #shoe_time(foo) #2.0001142024993896
  26. #shoe_time(bar) #3.001171588897705
  27. foo() #foo...... # 2.0001144409179688
  28. bar() # bar......
  29. # 3.00017142295837

带参数的被装饰函数

  1. #功能函数加参数
  2. import time
  3. def shoe_time(f):
  4. def inner(x,y):
  5. start = time.time()
  6. f(x,y)
  7. end = time.time()
  8. print(end-start)
  9. return inner
  10. @shoe_time
  11. def add(a,b):
  12. print(a+b)
  13. time.sleep(3)
  14. #@shoe_time
  15. # def foo():
  16. # print("foo......")
  17. # time.sleep(2)
  18. # @shoe_time
  19. # def bar():
  20. # print("bar......")
  21. # time.sleep(3)
  22. #
  23. add(1,3) #
  24. #3.000171661376953
  25.  
  26. #不定长参数
  27. import time
  28. def shoe_time(f):
  29. def inner(*x,**y):
  30. start = time.time()
  31. f(*x,**y)
  32. end = time.time()
  33. print(end-start)
  34. return inner
  35. @shoe_time
  36. def add(*a,**b):
  37. sum = 0
  38. for i in a:
  39. sum += i
  40. print(sum)
  41. time.sleep(3)
  42. #@shoe_time
  43. # def foo():
  44. # print("foo......")
  45. # time.sleep(2)
  46. # @shoe_time
  47. # def bar():
  48. # print("bar......")
  49. # time.sleep(3)
  50. #
  51. add(1,3,4,6,78) #
  52. #3.000171661376953

带参数的装饰器

  装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@shoe_time,该装饰器唯一的参数就是执行业务的函数。装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。

  1. #带参数的装饰器
  2.  
  3. import time
  4. def logger(flag=""):
  5. def shoe_time(f):
  6. def inner(*x,**y):
  7. start = time.time()
  8. f(*x,**y)
  9. end = time.time()
  10. print(end-start)
  11. if flag == "true":
  12. with open("日志记录", "a",encoding="utf8") as g:
  13. g.write("值为: %s 时间为: %s\n"%(f(*x),(end-start)))
  14. return inner
  15. return shoe_time
  16. @logger("true") #@show_time
  17. def add(*a,**b):
  18. Sum = 0
  19. for i in a:
  20. Sum += i
  21. print(Sum)
  22. time.sleep(3)
  23. return Sum
  24. @logger("abc")
  25. def foo():
  26. print("foo......")
  27. time.sleep(2)
  28. # @shoe_time
  29. # def bar():
  30. # print("bar......")
  31. # time.sleep(3)
  32.  
  33. add(1,3,4,6,78) #
  34. #3.000171661376953
  35. foo()

  @logger("true") 做了两件事:

(1)@ogger("true"):得到闭包函数show_time,里面保存环境变量flag

(2)@time   :add=show_time(add)

上面的logger是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器(一个含有参数的闭包函数)。当我 们使用@logger("true")调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。

 

python 学习笔记7(装饰器)的更多相关文章

  1. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  2. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  3. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  4. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  5. python学习笔记之装饰器、生成器、内置函数、json(五)

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...

  6. python学习笔记之装饰器、递归、算法(第四天)

    参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...

  7. Python学习笔记之装饰器原理

    def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...

  8. python学习之day5,装饰器,生成器,迭代器,json,pickle

    1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...

  9. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  10. 从零开始的Python学习Episode 11——装饰器

    装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...

随机推荐

  1. fir.im Weekly - 2015 年开发者调查报告

    终于一脚迈入了 2016 年.无论你是否准备好,未来已经汹涌扑来-- 新年第一期的 fir.im Weekly 干货颇多,来看一看:) 2015 Developer Survey stackoverf ...

  2. mysql-5.7.17-winx64免安装版,win10环境下安装配置

    下载地址:http://dev.mysql.com/downloads/file/?id=467269 1.解压到自定义目录:我解压到了D盘的根目录 2.复制my-default.ini 重命名 my ...

  3. Android WebView 总结 —— 使用HTML5播放视频及全屏方案

    在APP开发的过程中,会碰到需要在WebView中播放视频的需求,下面讲解一下如何在WebView中使用html5播放视频. 1.让视频在各个Android版本能够正常播放 在AndroidManif ...

  4. ajax获取json对象

    ajax获取json对象 ajax获取json数据,都是一个原理,设置response 的Content-Type:application/json,这样浏览器自动会解析为json对象 $result ...

  5. @@IDENTITY与SCOPE_IDENTITY()

    在一条 INSERT.SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含语句生成的最后一个标识值.如果语句未影响任何包含标识列的表,则 @@IDENTITY 返回 NULL. ...

  6. word-wrap: break-word; break-word: break-all;区别

    word-break:break-all和word-wrap:break-word都是能使其容器如DIV的内容自动换行. 它们的区别就在于: 1,word-break:break-all 例如div宽 ...

  7. Android实现下滑和上滑事件

    做过开发的对于下滑刷新与上滑加载都一定不陌生,因为我们在很多时候都会使用到,那对对于这个效果如何实现呢?相信难道过很多小伙伴,今天我就带领大家一道通过第三方组件快速完成上述效果的实现,保准每位小伙伴都 ...

  8. Ajax在IE浏览器会出现中文乱码解决办法

    在AJAX浏览器来进行发送数据时,一般它所默认的都是UTF-8的编码. Ajax在IE浏览器会出现中文乱码的情况!解决办法如下 <script type="text/javascrip ...

  9. 【踩坑经历】一次Asp.NET小网站部署踩坑和解决经历

    2013年给1个大学的小客户部署过一个小型的Asp.NET网站,非常小,用的sqlite数据库,今年人家说要换台服务器,要重新部署一下,好吧,虽然早就过了服务时间,但无奈谁叫人家是客户了,二话不说,上 ...

  10. Prim算法(二)之 C++详解

    本章是普里姆算法的C++实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/sk ...