一。LEGB函数作用域的优先级和解析

函数是function的一个对象,被调用完后内部变量就会被回收,被引用的除外(例如return的变量)

1.   local :函数内部作用域

2.  enclosing :函数内部和内嵌函数之间(一般是闭包使用)

3.  global :全局作用域

4.  build-in :内置作用域(Python自带的)

当多个作用域有相同的变量时,优先级高的会覆盖优先级低的,优先级从高到低1到4.

二。闭包

1.  什么是闭包

>>> def my_func(val):
...     def func():
...         print val
...     return func
...
>>> f = my_func('a')
>>> f()
a
>>> 

在my_func这个函数里,内嵌的func函数就是闭包,而闭包调用了enclosing作用域的val,my_func函数调用完后,val理应被回收了,但却还能被闭包调用,这是因为闭包的__closure__属性。

2. 闭包的__closure__属性

>>> def my_func(val):
...     print '%x' % id(val)
...     def func():
...         print val
...     return func
...
>>> f = my_func('a')
10ce56580
>>> print f.__closure__
(<cell at 0x10cf52980: str object at 0x10ce56580>,)
>>> 

可以看到闭包的__closure__属性保存了一个内存地址,而这个内存地址就是my_func函数里变量val的内存地址。这就是val没被回收的原因,这是闭包的一个强大的作用之一。

三。装饰器(Decorator): 在代码运行期间动态增加功能的方式。

1.  用闭包装饰函数my_func_01,为他添加打印的b的功能

>>> def my_func(fun):
...     def func():
...         print 'b'
...         return fun()
...     return func
...
>>> def my_func_01():
...     print 'a'
...
>>> my_func_01 = my_func(my_func_01)
>>> my_func_01()
b
a
>>>

2.  用语法糖@简化闭包的装饰

>>> def my_func(fun):
...     def func():
...         print 'b'
...         return fun()
...     return func
...
>>> @my_func
... def my_func_01():
...     print 'a'
...
>>> my_func_01()
b
a
>>> 

所以可知道@my_func就等于 my_func_01 = my_func(my_func_01)

四。简单函数装饰

为my_fun(a) 函数添加一个打印功能   print 'add_fun'

@add_log  就相当于   my_fun = add_log(my_fun)

>>> def add_log(func):
...     def wrapper(*args,**kw):
...             print 'add_fun'
...             return func(*args,**kw)
...     return wrapper
...
>>> @add_log
... def my_fun(a):
...     print 'my_fun'
...     return 'a'
...
>>> my_fun(4)
add_fun
my_fun
'a'
>>> 

my_fun 指向了新的函数 wrapper(*args,**kw) , return func(*args,**kw) 而不是 return func ,这样一来,my_fun 所传入的参数就要和 my_fun(a) 的参数统一起来(当然也可以这样 my_fun(*args,**kw)) , 然后返回 func(*args,**kw) 的执行结果给 my_fun 变量,就实现了装饰作用。

五。带参数的装饰器

可以传入参数的装饰器,也可以这样 def add_log(*args,**kw): 来传多个参数。

@add_log('qwe')    就相当于 my_fun = add_log('wer')(my_fun) , 也就相当于 my_fun1 = add_log('wer') 和 @my_fun1 结合.

>>> def add_log(text):
...     def log_decorator(func):
...             def wrapper(*args,**kw):
...                 print 'add_fun'
...                 print text
...                 return func(*args,**kw)
...         return wrapper
...     return log_decorator
...
>>> @add_log('qwe')
... def my_fun(a):
...     print 'my_fun'
...     return 'a'
...
>>> my_fun(4)
add_fun
qwe
my_fun
'a'
>>> 

六。完善装饰器

my_fun 指向了新的函数 ,那一些属性就不是原来 my_fun 函数的了,这对有些依赖函数签名的代码执行就会出错(其实并不懂啥是依赖函数签名的代码0.0)。

>>> my_fun.__name__
'wrapper'
>>> 

就要在装饰器里添加 wrapper.__name__ = my_fun.__name__ 和 wrapper.__doc__ = my_fun.__doc__ 等代码,可以直接用Python内置的functools.wraps来处理。

>>> import functools
>>> def add_log(func):
...     @functools.wraps(func)
...     def wrapper(*args,**kw):
...             print 'add_fun'
...             return func(*args,**kw)
...     return wrapper
...
>>> @add_log
... def my_fun(a):
...     print 'my_fun'
...     return 'a'
...
>>> print my_fun.__name__
my_fun
>>> 

最后需要指出,由于我们把原函数签名改成了(*args, **kw),因此,无法获得原函数的原始参数信息。即便我们采用固定参数来装饰只有一个参数的函数

四。参考

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819879946007bbf6ad052463ab18034f0254bf355000

http://www.imooc.com/code/6067

https://www.imooc.com/learn/581

转载于:https://www.cnblogs.com/GH-123/p/7787163.html

装饰器Decorator(函数的装饰)相关推荐

  1. python高级语法装饰器_Python高级编程——装饰器Decorator超详细讲解上

    Python高级编程--装饰器Decorator超详细讲解(上篇) 送你小心心记得关注我哦!! 进入正文 全文摘要 装饰器decorator,是python语言的重要特性,我们平时都会遇到,无论是面向 ...

  2. [转载] Python学习笔记——用装饰器decorator和Memoization记忆化提高效率,原理讲清楚了

    参考链接: 在Python中使用装饰器进行记忆 Python学习笔记--用装饰器decorator和Memoization记忆化提高效率 装饰器Memoization记忆化运用`functools`中 ...

  3. 理解TS装饰器Decorator

    理解TS装饰器Decorator 介绍 类装饰器 方法装饰器 介绍 详细的关于ts中装饰器的使用和语法可以参考 ts官网中decorator这一章节,或者阮一峰的ts教程的decorator章节这里这 ...

  4. Python: 使用装饰器“@”取得函数执行时间

    class A(): Python: 使用装饰器"@"取得函数执行时间 - oldJ的学习笔记 - 博客频道 - CSDN.NET Python: 使用装饰器"@&quo ...

  5. python类装饰器详解-Python 装饰器详解

    开放封闭原则: 开放对扩展 封闭修改源代码 改变了人家调用方式 装饰器结构 """ 默认结构为三层!!!每层返回下一层内存地址就可以进行执行函数, 传参:语法糖中的传参可 ...

  6. py函数式编程(高阶函数map/reduce/filter/sorted、闭包函数/返回函数、匿名函数lamber、@装饰器decorator、偏函数functool.partial())

    #py函数式编程.py #高阶函数map/reduce/filter/sorted.闭包函数/返回函数.匿名函数lamber.@装饰器decorator.偏函数functool.partial()# ...

  7. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

    2019独角兽企业重金招聘Python工程师标准>>> 1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过 ...

  8. python函数装饰函数_Python精进-装饰器与函数对象

    本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...

  9. python装饰器函数-Python精进-装饰器与函数对象

    本文为<爬着学Python>系列第四篇文章. 从本篇开始,本专栏在顺序更新的基础上,会有不规则的更新. 在Python的学习与运用中,我们迟早会遇到装饰器,这个概念对于初识装饰器的新手来说 ...

最新文章

  1. 网页瀑布流效果实现的几种方式
  2. Spring Security源码解析(四)—— 过滤器
  3. 系统开发基础:UML中图的相关知识笔记(上)
  4. java ee基础知识_Java EE:基础知识
  5. python中time模块的时间戳和格式化日期_Python中的time模块与datetime模块
  6. 增删改数据库表中的字段名
  7. Python基础函数学习笔记(三)
  8. 马云获评《外交政策》全球十大思想者 影响全球经济变革
  9. 苹果mp3软件_第二十一期:喜马拉雅听书x2m格式转换mp3
  10. python学习笔记(六):if语句之处理数据
  11. android 通知写法_Android消息通知-Notifation
  12. 探索开源工作流引擎Azkaban在MRS中的实践
  13. 波士顿房价预测python决策树_波士顿房价预测 - 最简单入门机器学习 - Jupyter
  14. Pytorch中transforms.Compose()的使用
  15. js word 预览_Node.js微服务实践(二)
  16. 高校教师科研文献管理系统
  17. php养老院管理系统论文,基于Web的养老院管理系统的设计任务书
  18. 天猫双11为什么能抗住90秒100亿?消费狂欢背后隐藏了哪些架构技术?
  19. 亲密接触中国SaaS应用(下)
  20. c语言 时间函数,C 日期和时间函数

热门文章

  1. 剑指offer面试题[35]-第一个只出现一次的字符
  2. 亲密关系沟通-【正向情绪】创造一场愉快的沟通体验
  3. 还没休年假的小伙伴注意了...事关你的合法权益
  4. 10分钟学会数据库压力测试
  5. 现在公司都不缺人了吗?软件测试工作经历3年居然被坑了?防不胜防
  6. PAT甲级1056(queue的用法)
  7. ajax control toolkit vs2013,如何将Ajax Control Toolkit控件安装到Visual Studio 2005工具箱
  8. 修改mysql数据库默认字符集_MySQL数据库之修改mysql默认字符集的两种方法详细解析...
  9. 可视化类激活的热力图
  10. php在图片左上角加入水印,如何在PHP中将图像添加到图像上,如水印