函数基础
关于函数基础,可以查看我的另一篇博客:http://yunjianfei.iteye.com/blog/2186064
与本文相关的,有两个重要概念:变量作用域(scope)与生命周期(lifetime)
如果对于这两个概念有所疑惑,可以先去了解一下。
嵌套函数
python是允许创建嵌套函数的,也就是说我们可以在函数内部定义一个函数,这些函数都遵循各自的作用域和生命周期规则。
#!/usr/bin/env python def outer(): x = 1 def inner(): print x # 1 inner() # 2 outer()
输出结果:
这个例子比普通的函数定义看起来复杂了一点,实际上都是很合理的。
1. #1的地方,python寻找名为x的local变量,在inner作用域内的locals中寻找不到,python就在外层作用域中寻找,其外层是outer函数。x是定义在outer作用域范围内的local变量。
2. #2的地方,调用了inner函数。这里需要特别注意:inner也只是一个变量名,是遵循python的变量查找规则的(Python先在outer函数的作用域中寻找名为inner的local变量)
函数在python中是first-class对象
上面这句话看着有点抽象,简单点来说,在python中所有的东西都是对象,函数也是对象,看下面的代码:
#!/usr/bin/env python a = 1 print a.__class__ print issubclass(a.__class__, object) # all objects in Python inherit from a common baseclass def foo(): pass print foo.__class__ # 1 print issubclass(foo.__class__, object)
输出结果:
True
<type 'function'>
True
可以看到foo和变量a一样,都是顶级父类object的子类。a是一个int变量,foo是一个函数。
所以,函数没有什么特殊的,它和python里的其他东西一样,都属于对象,其父类是object。这意味着,
1. 函数和其他变量是一样,变量是可以传递和修改值的,函数也可以作为变量
2. 函数也可以作为函数的参数或者函数的返回值。
如下的例子:
#!/usr/bin/env python def add(x, y): return x + y def sub(x, y): return x - y def apply(func, x, y): # 1 return func(x, y) # 2 print apply(add, 2, 1) # 3 print apply(sub, 2, 1)
执行结果
1
这个例子中,add和sub就是两个普通的函数对象。#1中,func这个参数用来接收函数变量(和其他参数接收变量一样)。在#2处,用来执行func参数传递进来的函数。在#3处,我们把add函数作为参数传递给apply,在apply中执行,并返回结果。
再看一个例子:
#!/usr/bin/env python def outer(): def inner(): print "Inside inner" return inner # 1 foo = outer() #2 print foo foo()
输出结果:
Inside inner
1. 在#1处, 我们返回了inner变量(这个变量是函数标签)。
注意:这里并没有去调用inner,调用的话是inner()
2. 在#2处,我们将outer函数返回的结果赋值给foo变量,foo返回的是inner函数的标签(注意输出结果), 概念类似c语言中的函数指针
3. 最后执行foo的时候,实际上执行的是inner。
以上的例子充分说明,函数完全可以看做是变量,可以把它赋值给其他变量,且有变量作用域、变量生存周期等。
闭包(Closures)
再来看一个例子:
#!/usr/bin/env python def outer(): x = 1 def inner(): print x # 1 return inner foo = outer() print foo.func_closure #2 doctest: +ELLIPSIS foo()
输出结果:
在这个例子中,我们可以看到inner函数作为返回值被outer返回,然后存储在foo变量中,我们可以通过foo()来调用它。但是真的可以跑起来吗?让我们来关注一下作用域规则。
python里运行的东西,都按照作用域规则来运行。
1. x是outer函数里的local变量
2. 在#1处,inner打印x时,python在inner的locals中寻找x,找不到后再到外层作用域(即outer函数)中寻 找,找到后打印。
看起来一切OK,那么从变量生命周期(lifetime)的角度看,会发生什么呢:
1. x是outer的local变量,这意味着只有outer运行时,x才存在。那么按照python运行的模式,我们不能在 outer结束后再去调用inner。
2. 在我们调用inner的时候,x应该已经不存在了。应该发生一个运行时错误或者其他错误。
但是这一些都没有发生,inner函数依旧正常执行,打印了x。
Python支持一种特性叫做函数闭包(function closures):在非全局(global)作用域中定义inner函数(即嵌套函数)时,会记录下它的嵌套函数namespaces(嵌套函数作用域的locals),可以称作:定义时状态,可以通过func_closure 这个属性来获得inner函数的外层嵌套函数的namespaces。(如上例中#2,打印了func_closure ,里面保存了一个int对象,这个int对象就是x)
注意:每次调用outer函数时,inner函数都是新定义的。上面的例子中,x是固定的,所以每次调用inner函数的结果都一样。
下面我们看一个不同的例子:
#!/usr/bin/env python def outer(x): def inner(): print x # 1 return inner print1 = outer(1) print2 = outer(2) print print1.func_closure print1() print print2.func_closure print2()
输出结果:
1
(<cell at 0x147d3360: int object at 0x146b2cf0>,)
2
在这个例子中,我们能看到闭包实际上是记录了外层嵌套函数作用域中的local变量。通过这个例子,我们可以创建多个自定义函数。
思维扩展一下,上面这个例子,很容易让人想到面向对象编程:
1. outer是inner的构造器
2.x是inner的一个私有变量
这里主要是帮助读者理解闭包的概念,
下面附上几个链接,帮助更好的理解:
http://ynniv.com/blog/2007/08/closures-in-python.html
http://www.shutupandship.com/2012/01/python-closures-explained.html
相关推荐
文章目录第一部分 函数对象第二部分 高阶函数第三部分 嵌套函数第四部分 闭包4.1 闭包的定义4.2 nonlocal——声明范围 第一部分 函数对象 函数是Python中的第一类对象 可以把函数赋值给变量 对该变量进行调用,可...
其实在函数式编程中,函数里面还可以嵌套函数,如下面这样 def foo(): print(hello world in foo) def bar(): print(hello world in bar) 此时我们调用foo函数,执行结果会是什么样子的呢?? hello world in ...
闭包必须返回嵌套函数。 嵌套函数必须引用一个外部的非全局的局部自由变量。 举个栗子 # 嵌套函数但不是闭包 def nested(): def nst(): print('i am nested func %s' % nested.__name__) nst() # 闭包函数 def ...
在Python中函数可以作为参数进行传递,而也可以赋值给其他变量(类似Javascript,或者C/C++中的函数指针); 类似Javascript,Python支持函数嵌套,Javascript...与嵌套函数紧密相关的就是闭包特性,举一个简单的例子
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不...
本文实例讲述了Python高级特性之闭包与装饰器。分享给大家供大家参考,具体如下: 闭包 1.函数参数: (1)函数名存放的是函数的地址 (2)函数名()存放的是函数内的代码 (3)函数名只是函数代码空间的引用,当函数名...
闭包是Python装饰器的基础。要理解闭包,先要了解Python中的变量作用域规则。 变量作用域规则 首先,在函数中是能访问全局变量的: ...上面的嵌套函数就是闭包。 闭包 是指延伸了作用域的函数,在其中能够访问未在
本文实例讲述了Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作。分享给大家供大家参考,具体如下: 实例对象也可以实现闭包的功能,不过实例对象消耗的资源(内存)比闭包多。 demo.py(闭包): # 闭包,...
1.先讲函数嵌套,很简单的例子,如: print(len('我和你')) 这样就很好理解了。 2.关于多个函数共同运行,最...与嵌套函数紧密相关的就是闭包特性,举一个简单的例子: >>> def test(): ... a = {'name': 'wyj'} ...
在进入闭包之前,我们必须先了解一个嵌套函数和非局部变量。 在函数中定义另一个函数称为嵌套函数。嵌套函数可以访问包围范围内的变量。 在Python中,这些非局部变量只能在默认情况下读取,我们必须将它们显式地声明...
主要介绍了Python函数基础,结合实例形式详细分析了函数嵌套,命名空间,函数对象,闭包函数等相关概念、原理、用法及操作注意事项,需要的朋友可以参考下
文章目录1、高阶函数的特点2、高阶函数2.1 接受函数作为参数2.2 返回值为函数(也称作闭包)2.2.1 闭包的好处 1、高阶函数的特点 什么叫高阶函数呢? 类比数学中的定义,数学中是指三次及以上的幂运算,那在这里我们...
关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包...
1.一等函数 在Python中,函数是一等公民(first class ...闭包是嵌套函数模型中的一个重要应用。外函数把内函数作为返回值返回,并且内函数中使用了外函数的局部变量,这样的情况下被返回的内函数被称为闭包(clos
关于闭包, 很多blog中都这样解释 :对于一个嵌套定义的函数,外层的函数的返回值是内层函数,而在内层函数中又引用了外层函数的局部变量,在外层函数执行后,其局部变量并非被回收,而会同返回的内层函数一同存在,...
├─千锋Python教程:第06章 函数与高阶函数(7集)) │ │ .DS_Store │ │ │ ├─code │ │ 10、函数也是一种数据.py │ │ 11、匿名函数.py │ │ 12、map&reduce;.py │ │ 13、filter.py │ │ 14、sorted....
python09——函数31. 高阶函数2. 闭包3. 装饰器的引入4. 装饰器的使用 1. 高阶函数 接收函数作为参数,或者将函数作为返回值返回的函数就是高阶函数 2. 闭包 将函数作为返回值也是高阶函数我们也称为闭包 闭包的好处...
3、内层嵌套函数对外部作用域有一个非全局变量的引用 闭包的作用: 实现数据锁定 装饰器的作用: 就是为已经存在的对象添加额外的功能。 常用场景: 插入日志、性能测试、事务处理、缓存、权限校验等 代码示例: ...