Python:闭包

闭包(Closure)

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

命名空间与作用域

我们可以把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系。在 Python 中,作用域实际上可以看做是“在当前上下文的位置,获取命名空间变量的规则”。在 Python 代码执行的任意位置,都至少存在三层嵌套的作用域:

  • local            最内层作用域,最早搜索,包含所有局部变量**(Python 默认所有变量声明均为局部变量)**
  • non-local    所有包含当前上下文的外层函数的作用域,由内而外依次搜索,这里包含的是非局部也非全局的变量
  • global         一直向上搜索,直到当前模块的全局变量
  • built-in        最外层,最后搜索的,内置(built-in)变量

在任意执行位置,可以将作用域看成是对下面这样一个命名空间的搜索:


scopes = {
    "local": {"locals": None,
             "non-local": {"locals": None,
                          "global": {"locals": None,
                                    "built-in": ["built-ins"]}}},
}
 

除了默认的局部变量声明方式,Python 还有globalnonlocal两种类型的声明(nonlocal是Python 3.x之后才有,2.7没有),其中 global 指定的变量直接指向(3)当前模块的全局变量,而nonlocal则指向(2)最内层之外,global以内的变量。这里需要强调指向(references and assignments)的原因是,普通的局部变量对最内层局部作用域之外只有**只读(read-only)**的访问权限,比如下面的例子:

>>>x = 100
>>def main():
    x += 1
    print(x)

>>>main()
Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    main()
  File "<pyshell#49>", line 2, in main
    x += 1
UnboundLocalError: local variable ‘x‘ referenced before assignment

这里抛出UnboundLocalError,是因为main()函数内部的作用域对于全局变量x仅有只读权限,想要在main()中对x进行改变,不会影响全局变量,而是会创建一个新的局部变量,显然无法对还未创建的局部变量直接使用x += 1。如果想要获得全局变量的完全引用,则需要global声明:

>>>x = 100
>>>def main():
    global x
    x += 1
    print(x)

>>>main()
print(x) # 全局变量已被改变
101

Python闭包练习

到这里基本上已经了解了 Python 作用域的规则,我们仿照 JavaScript 写一个计数器的闭包:

"""
/* JavaScript Closure example */
var inc = function(){
  var x = 0;
  return function(){
    console.log(x++);
  };
};
var inc1 = inc()
var inc2 = inc()
"""
# Python 3.6
def inc():
    x = 0
    def inner():
        nonlocal x
        x += 1
        print(x)
    return inner
inc1 = inc()
inc2 = inc()

inc1()
inc1()
inc1()
inc2()
1
2
3
1
    上面的例子中,inc1()是在全局环境下执行的,虽然全局环境是不能向下获取到inc()中的局部变量x的,但是我们返回了一个inc()内部的函数inner(),而inner()inc()中的局部变量是有访问权限的。也就是说inner()inc()内的局部作用域打包送给了inc1inc2,从而使它们各自独立拥有了一块封闭起来的作用域,不受全局变量或者任何其它运行环境的影响,因此称为闭包。

闭包函数都有一个__closure__属性,其中包含了它所引用的上层作用域中的变量:

print(inc1.__closure__[0].cell_contents)
print(inc2.__closure__[0].cell_contents)
[3]
[1]

原文出处: rainyear

参考

  1. 9.2. Python Scopes and Namespaces
  2. Visualize Python Execution
  3. Wikipedia::Closure

原文地址:https://www.cnblogs.com/kumata/p/9059878.html

时间: 2024-10-01 22:13:32

Python:闭包的相关文章

Python闭包与函数对象

1. Python闭包是什么 在python中有函数闭包的概念,这个概念是什么意思呢,查看Wikipedia的说明如下: “ In programming languages, closures (also lexical closures or function closures) are a technique for implementing lexically scoped name binding in languages with first-class functions. Ope

python闭包和装饰器(转)

一.python闭包 1.内嵌函数 >>> def func1(): ... print ('func1 running...') ... def func2(): ... print ('func2 running...') ... func2() ... >>> func1() func1 running... func2 running... 内部函数func2作用域都在外部函数func1作用域之内 如果试图在外部函数的外部调用内部函数将会报错 >>&

Python闭包的学习

Python闭包的学习 什么是闭包? 借用维基上解释:在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外.所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体.闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例. 好吧,看了这段定义的确不是还不能立即理解闭包到底是什么.不过,闭包并不是很难理解,往下看几个小例子就能明

Python闭包举例

Python闭包的条件: 1.函数嵌套.在外部函数内,定义内部函数. 2.参数传递.外部函数的局部变量,作为内部函数参数. 3.返回函数.外部函数的返回值,为内部函数. 举例如下: def line_conf(a, b): def y_point(x): return a*x+b return y_point line1 = line_conf(1, 0) line2 = line_conf(2, 1) list1 = [line1(x) for x in range(10)] list2 =

【Rollo的Python之路】Python 闭包:Colsure

Python 闭包:Closure. 定义: python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 闭包是由函数及其相关的引用环境组合而成的实体. 函 数是一等公民(First class value:第一类对象,我们不需要像命令式语言中那样借助函数指针,委托操作函数),函数可以作为另一个函数的参数或返回值,可以赋给一个变量.函数可 以嵌套定义,即在一个函数内部可以定义另一个函数,

Python 闭包函数

一.定义: 1. 定义在函数内部的函数 2. 包含对外部作用域名字的引用,而不是对全局作用域名字的引用那么该内部函数就称为闭包函数 x=1 def f1(): x=11111111111 def f2(): print(x) return f2 func=f1() 二.闭包函数的应用:惰性计算 def index(url): # url='https://www.python.org' def get(): # return requests.get(url).text print(reques

python闭包

声明 :初学python,此文主要作为笔记,知识面浅,若理解有误请多担待,指出错误更是感激不尽! 闭包 :当函数存在嵌套,并且子函数引用了父函数中的变量,可以访问这些变量的作用域就形成闭包.如果子函数没有访问父函数中的变量,就不存在闭包,闭包每次运行是能够记住引用的外部作用域的变量的值.形象点说就是有一个大盒子,里面有个小盒子,小盒子里面用到的一些东西是来自外部的大盒子的,那么这些来自大盒子的东西,就是闭包. 接下来全部使用例子来解释闭包! 例子 一 #这里定义的是一个求和函数 def lazy

Python闭包的高级应用-装饰器的实现

我们先看一个闭包的例子: from time import ctime def before_call(f): def wrapped(*args, **kargs): print 'before calling, now is %s' % ctime() return f(*args, **kargs) return wrapped def test(name): print 'hello, %s' % (name) if __name__ == '__main__': before_call

python 闭包中引用的变量值变更问题

python的闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变. 如下: def count():     fs = []     for i in range(1, 4):         def lazy_count(j):             def cou():                 return j*j             return cou         r = lazy_count(i)     

[python]闭包到底是什么鬼?

这些东西是我在慕课网,廖雪峰大神的python课中学到的.自己写成笔记的形式分享给大家. 先来看一段代码: 1 def f1(x): 2 return x*x 3 4 def new_fn(f): 5 def fn(j): 6 print 'print'+f.__name__ 7 return f(j) 8 return fn 9 10 g1 = new_fn(f1) 11 print g1(5) 运行结果: printf1 25 1.为什么会用到闭包? 在不修改f1函数的前提下,输出f1函数的