前言:在Python中,闭包是一种非常有用的功能!它通常与装饰器一起搭配使用,可以在不改变被装饰函数的功能的基础上,完成更多的功能。如权限认证。

一、如何定义闭包

  1.闭包就是两个嵌套的函数,外层函数返回内层函数的引用,而且外层函数必须携带参数!为什么外层函数必须要有参数呢?可以思考一下!

  基本格式如下:  

 def outer_fun(func):
     def inner_fun():
         pass
     return inner_fun

  2.与普通函数的区别:

   闭包的外层函数的变量可以在内存中保存着,有点像类;而普通函数一旦执行完,那么就要回收内存。

  3.万能闭包

def outer_func(func):
    def inner_func(*args, **kwargs):
        func(*args, **kwargs)
    return inner_func

  

二、装饰器

  1.什么是装饰器:@闭包的外层函数名

  2.装饰器的作用:不修改被装饰函数的功能外,再通过闭包的方式添加额外的功能!

  3.基本结构:    

 def outer_func(func):
     def inner_func():
         pass
     return inner_func

 @outer_func # test = outer_func(test)
 def test():
     pass

  重点:上述代码的第七行和第八行是重点,看到这个语法糖要想到其本质: test = outer_func(test)

  4.结论:

    (1). 装饰前的test函数和闭包外层函数的func是一样的;

    (2). 装饰后的test函数是闭包内层函数的引用,也就是说此时test指向了inner_func函数体;

    (3). 装饰器一般不改变原先函数的行为。

  5.装饰器的一个小问题

    与其说是装饰器的问题,不如说是闭包的问题!

    一个函数被装饰之后,它的函数名会发生变化,变成了闭包的内层函数名。那该怎么解决这个问题呢?

    使用funtools.wraps()这个装饰器就可以完美解决这个问题了,因为这个装饰器会保留被装饰函数的一些基本信息。

    

 import functools

 def outer_func(func):
     # 使用这个装饰器,可以保留被装饰函数的一些基本信息,如名称不变
     @functools.wraps(func)
     def inner_func(*args, **kwargs):
         func(*args, **kwargs)

     # inner_func.__name__ = func.__name__
     return inner_func

 @outer_func
 def test(*args, **kwargs):
     print('%s 正在运行。。。。' % test.__name__)

 test()

三、装饰器内存图解

  1.一个装饰器装饰一个函数的内存图解:

  

  2.两个装饰器装饰一个函数的内存图解

    

四、装饰器传参数

  1.结构:由三层函数构成的,即用一个函数把闭包给封装起来,这个函数必须带有参数!

      最外层函数(set_args)返回闭包的外层函数的引用;

      闭包的外层函数(outer_fun)还是返回内层函数的引用。

    

 def set_args(args):
     def outer_fun(func):
         def inner_fun(*args, **kwargs):
             func(*args, **kwargs)
         return inner_func
     return outer_fun

  2.运行流程:    

 @set_args(')
 def test():
     print('test')

 test()

    (1).先执行@右边的函数,即先执行set_args('123'),

    (2).执行完set_args()后返回outer_fun的引用,此时就是test = outer_fun(test)这个熟悉的语法了,

    (3).接下来就执行被装饰的函数了。

Python高级--闭包与装饰器的更多相关文章

  1. Python函数编程——闭包和装饰器

    Python函数编程--闭包和装饰器 一.闭包 关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数).而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数.当其中一个 ...

  2. python之闭包与装饰器

    python闭包与装饰器 闭包 在函数内部定义的函数包含对外部的作用域,而不是全局作用域名字的引用,这样的函数叫做闭包函数. 示例: #-------------------------------- ...

  3. Python之闭包and装饰器

    闭包和装饰器是Python中非常重要的一种语法格式,在日常工作中应用非常广泛. 首先,我先为大家简单的介绍一下闭包的概念. 闭包:闭包是在函数嵌套的基础上,内层函数使用到外层函数的变量,且外层函数返回 ...

  4. 关于python的闭包与装饰器的实验

    首先看闭包,在嵌套函数内添加返回值,可以通过外部函数读取内部函数信息 #encoding=utf-8 #闭包应用 #先定义闭包函数,并使用 def outer(func): def inner(): ...

  5. python中闭包和装饰器

    前言: 编程语言发展的过程中,我们为了提高代码利用率,发明了函数式编程.函数将代码封装起来,我们需要用到此功能函数的时候,调用一下就可以了.但是使用的过程中,也遇到了一些问题,比如函数实现的功能不够, ...

  6. Python作用域-->闭包函数-->装饰器

    1.作用域: 在python中,作用域分为两种:全局作用域和局部作用域. 全局作用域是定义在文件级别的变量,函数名.而局部作用域,则是定义函数内部. 关于作用域,我要理解两点:a.在全局不能访问到局部 ...

  7. python的闭包与装饰器

    原文发表在我的博客主页,转载请注明出处 前言 如果把python当作脚本语言,每次就是写个几十行上百行来处理数据的话,装饰器也许不是很必要,但是如果要开发一个大型系统,装饰器是躲不开的,最开始体会ry ...

  8. Python的闭包和装饰器

    什么是闭包 python中函数名是一个特殊的变量,它可以作为另一个函数的返回值,而闭包就是一个函数返回另一个函数后,其内部的局部变量还被另一个函数引用. 闭包的作用就是让一个变量能够常驻内存. def ...

  9. python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)

    转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...

随机推荐

  1. Linux进程间的通信方式和原理

    进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放.可以认为进程是一个程序的一次执行过程. 进程通信的概念 进程用户空间是 ...

  2. Navicat相关应用及注意事项

    一.MySQL数据类型 1.数值型 SMALLINT: 2个字节 INT: 4个字节      // age int(10) INTEGER:INT的同义词 BIGINT : 8个字节 FLOAT : ...

  3. elasticsearch6.7 04.API规范

    API Conventions elasticsearch的REST的API是使用HTTP的JSON格式暴露的. 除非另有说明,本章中列出的约定可以在整个REST API中应用. 多索引 索引名称支持 ...

  4. centos7下没有iptables

    从centos7开始使用linux,之前版本的没有深入了解过,今天要开放个端口,需要有防火墙的相关操作,从网上查资料都是编辑/etc/sysconfig目录下面的iptables文件,可我进入这个文件 ...

  5. 使用Druid网上监控

    0.添加依赖 <!--druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artif ...

  6. c# 连等的写法都做了什么?

    在工作中遇到这样一个问题,批量对变量赋值相同的值时,如下: a = ; b = ; c = ; d = ; 我想这样写: a= b = c = d = ; 分别对应IL: Dup 复制计算堆栈上当前最 ...

  7. Android - AsyncTask你知道多少?

    http://www.cnblogs.com/qlky/p/5658070.html 为什么asyncTask最好在主线程初始化?在子线程怎么办? AsyncTask四个方法的执行顺序? mWorke ...

  8. Java生成代码(字节码)

    一.方式 代码生成器 & IDE 编译时代码生成: Pluggable Annotation Processing API 运行时代码生成: Compiler API 运行时生成字节码: cg ...

  9. CentOS 7 镜像下载

    新版本系统镜像下载(当前最新是CentOS 7.4版本) CentOS官网 官网地址 http://isoredirect.centos.org/centos/7.4.1708/isos/x86_64 ...

  10. 使用PHPExcel实现数据批量导入到数据库

    此例子只使用execel2003的.xls文档,若使用的是其他版本,可以保存格式为“Execel 97-2003 工作簿(*.xls)”即.xls文件类型即可! 功能说明:只能上传Excel2003类 ...