嵌套函数:

python允许创建嵌套函数。也就是说我们可以在函数里面定义函数,而且现有的作用域和变量生存周期依旧不变。

例子:

#encoding=utf-8

def outer():
    name="python"

def inner():#outer函数内部定义的函数
        print name
    return inner()#返回该内部函数

outer()

结果:

理解:

在inner函数中,python解析器需要找一个叫name的本地变量,查找失败后会继续在上层的作用域里面寻找,这个上层作用域定义在outer函数里,python函数可以访问封闭作用域。

对于outer函数中最后一句,返回inner函数调用的结果,需要知道非常重要一点就是,inner也仅仅是一个遵循python变量解析规则的变量名,python解释器会优先在outer的作用域里面对变量名inner查找匹配的变量。

把恰好是函数标识符的变量inner作为返回值返回回来,每次函数outer被调用的时候,函数inner都会被重新定义,如果它不被当做变量返回的话,每次执行过后它将不复存在。

在python里,函数就是对象,它也只是一些普通的值而已。也就是说你可以把函数像参数一样传递给其他的函数或者说从函数了里面返回函数

return内层函数时不加括号,只返回函数的地址:

代码:

#encoding=utf-8

def outer():
    name="python"

def inner():#outer函数内部定义的函数
        return name
    return inner#返回该内部函数

print outer()

 结果:

此时执行外层函数outer(),返回的是内层函数的函数引用(函数名称)--inner,想要执行内层函数,需要在outer()后边再加个括号,即outer()(),才会让内层函数执行

代码:

#encoding=utf-8

def outer():
    name="python"

def inner():#outer函数内部定义的函数
        return name
    return inner#返回该内部函数

print outer()()

结果:

函数作为变量:

例子:

#encoding=utf-8

def add(x,y):
    return x+y

def sub(x,y):
    return x-y

def apply(func,x,y):
    return func(x,y)

print "apply(add,2,1):",apply(add,2,1)
print "apply(sub,2,1):",apply(sub,2,1)
结果:

apply函数准备接收一个函数的变量,它也只是一个普通的变量而已,和其他变量一样。然后我们调用传进来的函数:“()代表着调用的操作,并且调用变量包含的值”。

在函数外,我们也能看到传递函数并没有什么特殊的语法,函数的名称只是和其他变量一样的表标识符而已。

闭包的理解:

先看个例子

#encoding=utf-8

def outer():
    name="python"
    def inner():
        print name
    return inner

res=outer()
res()
print res.func_closure#打印闭包里包含哪些外部变量
结果:

例中,inner作为一个函数被outer返回,保存在变量res中,并且还能够调用res()。为什么能调用呢?

通过上面变量的作用域和生存周期我们不难明白,name是函数outer里的一个局部变量,也就是说只有当outer正在运行时,该变量才会存在。

根据python的运行模式,我们是没法在函数outer执行退出之后还能继续调用inner函数的,并且在inner函数被调用时,变量name早已不存在了,但是为什么我们调用成功了呢?

这就回到了我们的闭包这个问题上了,python支持一个叫函数闭包的特性。

啥是闭包?

如果一个函数定义在另一个函数的作用域内,并且引用了外层函数的变量,则该函数称为闭包。闭包是Python所支持的一种特性,它让在非global scope定义的函数可以引用其外围空间中的变量,这些外围空间中被引用的变量叫做这个函数的环境变量。环境变量和这个非全局函数一起构成了闭包。

上例中的inner()函数就是一个闭包,它本身也是一个函数,而且还可以访问本身之外的变量。这能够通过查看函数的func_closure属性得出结论,这个属性里面包含封闭作用域里面的值(只会包含被捕捉到的值,比如name,如果在outer里面还定义了其他的值,封闭作用域里面是不会有的)

每次函数outer被调用时,inner函数都会被重新定义,上面每次返回的函数inner结果都一样,因为name没变。

如下例所示,我们将函数稍微改动一下,结果就不一样了

代码:

#encoding=utf-8

def outer(name):
    def inner():
        print name
    return inner

res1=outer("python")#返回闭包
res2=outer("java")#返回闭包
res1()#执行函数
res2()
结果:

分析:

在之前的例子中

def outer():
    name="python"
    def inner():
        print name
    return inner

外层函数后运行后,返回一个函数+函数需要的变量

name = "python"

def inner() :

print name

上边三行是整体返回的内容

如果在外层函数再加个外部的整形变量,在里面的函数中引用:

#encoding=utf-8

def outer():
    name="python"
    nbr=12
    def inner():
        print name
        print nbr
    return inner#不加括号就是返回函数对象,不是函数调用

res=outer()
res()#调用inner函数
print res.func_closure#打印闭包里包含哪些外部变量
结果:

D:\>python test.py
python
12
(<cell at
0x0000000004E56CA8: str object at 0x0000000004E58760>, <cell at
0x0000000004E56F78: int object at 0x0000000004E362C0>)

其中res = outer()是把inner函数对象赋值给res,因为没有括号,所以不是调用而是返回个函数对象

res()是调用inner函数

print res.func_closure是打印闭包里包含哪些外部变量,可以看到结果里有两个:即python和12

(<cell at 0x0000000004E56CA8: str object at 0x0000000004E58760>, <cell at 0x0000000004E56F78: int object at 0x0000000004E362C0>)

闭包特点:

一个函数返回的函数对象,这个函数对象执行的话依赖非函数内部的变量值,这个时候,函数返回的实际内容如下:
1 函数对象
2 函数对象需要使用的外部变量和变量值

以上就是闭包

闭包必须嵌套在一个函数里,必须返回一个调用外部变量的函数对象,才是闭包

 

在上边的例子中,相对于inner来说 ,outer函数就是它得全局变量,就好像你存粹写个函数会用到函数外面环境定义得全局变量一样 ,都是相对的概念

通俗理解就是:里面函数执行  ,需要用到外面函数的一个变量 ,所以,就把外面变量和里面这个函数合到一块,合到一块的这两个东西就是闭包

python中函数嵌套、函数作为变量以及闭包的原理的更多相关文章

  1. [转]关于python中带下划线的变量和函数的意义

    Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下,不同程序员编写的 Python 代码可以保持最大程度的相似风格.这样就易于阅读, ...

  2. python中如何调用函数交换两个变量的值

    python中如何调用函数交换两个变量的值 所有代码来在python3.7.1版本实现 以下实例通过用户输入两个变量,并相互交换:  方法一: def swap(a,b): # 创建临时变量,并交换 ...

  3. python中的生成器函数是如何工作的?

    以下内容基于python3.4 1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函 ...

  4. 举例详解Python中的split()函数的使用方法

    这篇文章主要介绍了举例详解Python中的split()函数的使用方法,split()函数的使用是Python学习当中的基础知识,通常用于将字符串切片并转换为列表,需要的朋友可以参考下   函数:sp ...

  5. python中的map()函数

    MapReduce的设计灵感来自于函数式编程,这里不打算提MapReduce,就拿python中的map()函数来学习一下. 文档中的介绍在这里: map(function, iterable, .. ...

  6. 揭秘 Python 中的 enumerate() 函数

    原文:https://mp.weixin.qq.com/s/Jm7YiCA20RDSTrF4dHeykQ 如何以去写以及为什么你应该使用Python中的内置枚举函数来编写更干净更加Pythonic的循 ...

  7. (转)Python中的split()函数的用法

    Python中的split()函数的用法 原文:https://www.cnblogs.com/hjhsysu/p/5700347.html Python中有split()和os.path.split ...

  8. Python 函数对象-函数嵌套-名称空间与作用域-闭包函数

    今日内容: 1. 函数对象 函数是第一类对象: 指的是函数名指向的值可以被当中数据去使用 1.可以被引用 2.可以当做参数传给另一个函数 3.可以当做一个函数的返回值 4.可以当做容器类型的元素 2. ...

  9. Python中的lambda函数介绍

    Lambda函数,即Lambda 表达式(lambda expression),是一个匿名函数(不存在函数名的函数),Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lam ...

随机推荐

  1. InnoDB启用大内存页

    在 Linux 操作系统上运行内存需求量较大的应用程序时,由于其采用的默认页面大小为 4KB,因而将会产生较多 TLB Miss 和缺页中断,从而大大影响应用程序的性能.当操作系统以 2MB 甚至更大 ...

  2. 帝国cms搜索关键字调用标签(showsearch)怎么用

    前面ytkah介绍了如何让帝国CMS7.2搜索模板支持动态标签调用,现在我们来说说怎么调用帝国cms搜索关键字调用标签(showsearch).在帝国cms后台那边的使用方法:[showsearch] ...

  3. CentOS安装Docker CE

    安装Docker CE(免费版) docker EE企业版您可以根据需要以不同方式安装Docker CE: 大多数用户 设置Docker的存储库并从中进行安装,以便于安装和升级任务.这是推荐的方法. ...

  4. Python3学习之路~8.2 socket简单实例 实现ssh 发送大量数据

    实例1: 利用socket模拟客户端和服务器端各自收发一次数据: #Author:Zheng Na # 客户端 import socket # 声明socket类型,同时生成socket连接对象 cl ...

  5. 数据库---初识sql语句

    初识sql语句 SQL语言主要用于存取数据.查询数据.更新数据和管理关系数据库系统,SQL语言由IBM开发.SQL语言分为3种类型: DDL语句     数据库定义语言: 数据库.表.视图.索引.存储 ...

  6. awk命令分析日志的简单笔记

    awk是一个文本分析工具,可以用来进行流量日志分析 之前无意中看到了这个命令,简单记一下笔记 ,在打线下的时候可能会有用 awk有3个不同版本: awk.nawk和gawk,未作特别说明,一般指gaw ...

  7. sort(排序) qsort(快排) bsearch(二分查找)

    sort: 一.对int类型数组排序 int a[100]; int cmp ( int a , int b ) //不必强制转换 { return a < b;//升序排列. } sort ( ...

  8. shell的函数返回值

    1.默认function的返回值包含0 和1,执行成功,返回0,执行失败,返回1,可以采用$?来获取执行结果 2.函数如何返回字符串呢,可以采用echo函数 #!/bin/bashfunction t ...

  9. 部分还款-还款试算接口-python

    一.swagger-ui中 二.python中调用接口,出现的问题: 解决办法: import requests # 还款试算接口 ur1='http://10.253.43.83:8399/repa ...

  10. HttpwebRequest - 带ViewState的网页POST请求

    这是我今天下午碰到的案例,一个退订页面的post请求,请求头信息都很明确,but看看下面这个请求体,除了最后一个key是我的页面控件名称,其他的几个ViewState相关都是what呢?(ViewSt ...