精华内容
下载资源
问答
  • #第一种解决方法:创建一个闭包,使用默认参数立即绑定它的参数 def testFun1(): temp = [lambda x, i = i : i * x for i in range(4)]; return temp; for everyLambda in testFun1(): print(everyLambda(2)); ...
  • L: local 函数内部作用域E: enclosing 函数内部与内嵌函数之间G: global 全局作用域B: build-in 内置作用二、闭包闭包的本质是一个函数,包含两个部分:内部函数体本身以及对外部函数变量的引用,这个变量(自由...

    Python函数作用域遵循LEGB顺序

    一、什么是LEGB?

    L: local 函数内部作用域

    E: enclosing 函数内部与内嵌函数之间

    G: global 全局作用域

    B: build-in 内置作用

    二、闭包

    闭包的本质是一个函数,包含两个部分:内部函数体本身以及对外部函数变量的引用,这个变量(自由变量: free variables)的引用不会因为外部函数执行完毕而消失。

    构成闭包的三个条件:

    1、函数内嵌函数;

    2、内函数引用外函数定义的变量

    3、外函数返回内函数的引用。

    三、nonlocal:

    通过关键字在内函数里面声明引用的外函数的不可变变量,可以实现对变量的修改

    未声明,报错声明,正常输出

    未对变量进行修改,正常输出

    四、global

    global是声明全局变量的关键字,类似于nonlocal的用法,在函数内部通过global声明后才可以对不可变类型全局变量进行修改。

    global使用

    五、可变变量

    对于可变类型变量,在函数中的使用可以理解为对其的引用,可以不通过声明直接修改其内部空间的元素。

    六、外部变量的使用

    你可能会想到的是,被调用时,他们将分别返回1,4,9,但实际返回的都是9,根本原因是变量j不是函数内部定义变量(local)而是引用的自由变量,只有在函数调用时才会访问其引用的自由变量,而不是在定义的时候就访问,在循环结束的时候,j=3,所以返回的就是:3*3*1。为了避免这种情况,可以在循环的定义函数的过程中将j的值赋值给函数的内部变量

    七、函数变量的相关属性

    展开全文
  • python闭包变量迟绑定

    2018-03-18 14:33:30
    print([x(3) for x in foo()])[6, 6, 6, 6]上述问题产生的原因是Python闭包的延迟绑定。这意味着内部函数被调用时,参数的值在闭包内进行查找。因此,当任何由foo()返回的函数被调用时,i的值将在附近的范围进行查找...
    def foo():
        return [lambda x: i + x for i in range(4)]
    
    print([x(3) for x in foo()])
    [6, 6, 6, 6]

    上述问题产生的原因是Python闭包的延迟绑定。这意味着内部函数被调用时,参数的值在闭包内进行查找。因此,当任何由foo()返回的函数被调用时,i的值将在附近的范围进行查找。那时,不管返回的函数是否被调用,for循环已经完成,i被赋予了最终的值3。



    展开全文
  • 最近在看一些别人的代码的时候突然遇到了python的闭包,(我学python的时候一般都是用到哪里看到哪里)所以突然看到闭包这里刚开始一下子没看懂。所以在网上百度了下...python闭包了解:https://www.jianshu.com/...

    最近在看一些别人的代码的时候突然遇到了python的闭包,(我学python的时候一般都是用到哪里看到哪里)所以突然看到闭包这里刚开始一下子没看懂。所以在网上百度了下资料。有好几篇对于闭包的概念的解释我是可以理解的。但是到在闭包中引用循环的时候就有点没看懂那个代码。为此特别写了这个。和大家交流下,不对的地方欢迎大牛指正,谢谢

    python闭包了解:https://www.jianshu.com/p/e5377fa362a9

    就是这个,刚开始我以为返回的应该是1,4,9.但是后面看别人的博客说是等于9.我看了1天都没看懂和理解。

    到下午重新琢磨了下,突然开窍了。所以这里记录并和大家分享下

    def count():
        fs = []
        for i in range(1, 4):
            def f():
                 return i**2
            fs.append(f)
        return fs

    首先大家看下上面的这个函数count().它是一个嵌套函数,除此外他还带了一个循环。并且在循环末尾将内函数加到了它的列表里。这个看起来打眼一瞅我真的觉得fs.append(f)这句执行的时候应该是效果等同于fs.append(f())。但其实并不然。这里没带()的f其实并不是调用f方法。我们可以暂时将它理解为这个方法的物理地址(我因为不知道,所以先跟自己这么说去记忆,如果有大牛知道这个是啥可以告诉我,我完善下谢谢!)。所以

     

    1、在执行fs.append(f)的时候这里确实根据循环执行了三遍,证据如下。在上述代码下方加上如下代码,然后右键执行

     

    执行结果如下:

    C:\Users\15010\PycharmProjects\TestPro\venv\Scripts\python.exe C:/Users/15010/PycharmProjects/TestPro/pro/test.py
    [<function count.<locals>.f at 0x0000021B9BAAA620>, <function count.<locals>.f at 0x0000021B9BAAA840>, <function count.<locals>.f at 0x0000021B9BAAAB70>]

    Process finished with exit code 0

    注意:看下黑体加粗的部分,是我标注的执行结果。也就是说这是此时f中存储的对象。

    2、如果了解过for循环的人,那么此时就一定知道。目前外函数中i是等于3的。而内函数因为没有被调用(如果了解过闭包概念的人,应该也就知道这一点)。因此是没有被执行的

    3、然后此时若是执行f1()才相当于是在调用count()函数的内函数f(),那么这个时候传递给内函数的i因为外面的循环已经执行过了。因此此时的i=3.那么返回的值也就是9了。此时是不会再执行外函数了。因此这个时候再完毕后再去打印列表得到的列表内容预期应和之前 打印的结果相同。

     

     

    其实后面我在执行的时候还遇到一个问题,那就是单独调用f1()的时候会报错,没理解。这个问题先暂时搁置。如果后面我知道了在做补充,嘿嘿

    展开全文
  • 小引以前学 js 的时候第一次见到闭包,当时不甚了了,还为了应付面试强行记住了一个模棱两可的“定义”:在函数...最近工作需要,用起 python,又遇到闭包,这次看到了一些新奇有趣的资料,这才算大致把一些字面上的...

    小引

    以前学 js 的时候第一次见到闭包,当时不甚了了,还为了应付面试强行记住了一个模棱两可的“定义”:在函数中嵌套定义函数,并且在外层将内层函数返回,一同返回了外层函数的环境。当时从字面意思以及当时一个经典例子试图去理解闭包,加之”闭包”这个翻译也很不容易让人味出其中的道理,导致对其总感觉懵懵懂懂。最近工作需要,用起 python,又遇到闭包,这次看到了一些新奇有趣的资料,这才算大致把一些字面上的概念(first-class functions,bind,scope等等)贯通在一起,反过来对闭包有了更深的理解。

    引用资料列在最后,十分推荐大家去读读。

    作者:青藤木鸟Muniao's blog转载请注明出处

    概要

    计算机中有些英文专业词汇,字面直译,难免因缺少上下文而显得苍白拗口,须得多方铺垫,方能味得古怪下面的原理。闭包(closure)便是一个这样牵扯了许多上下文的概念,包括编程语言最基本的绑定(binding),环境(environments),变量作用域(scope)以及函数是第一等公民(function as the first-class)等等。

    Binding(绑定)

    在Python中,binding 是编程语言最基本的抽象手法,它将一个值绑定到一个变量上,并且稍后可以引用或者修改该变量。下面是几种不同层次的绑定,每组语句在运行时将一个名字与对应值绑定到其定义所在的环境中。

    包括将名字绑定到一块内存,通过赋值语句实现,当然函数调用时,形参和实参结合也是绑定:

    In [1]: square = 4

    将名字绑定到一组复合运算,即函数定义,利用 def 关键字实现:

    In [1]: def square(x):

    return x*x

    将名字绑定到一个数据集合,即类定义,使用 class 实现:

    In [1]: class square:

    def __init__(self, x):

    self.x = x

    def value(self):

    return self.x * self.xIn [1]: def square(x):

    return x*x

    依照执行顺序,多次同名绑定,后面会覆盖前面:

    In [1]: square = 3

    In [2]: square

    Out[2]: 3

    In [3]: def square(x):

    ...: return x * x

    ...:

    ...:

    In [4]: square

    Out[4]:

    In [5]: class square:

    ...: def __init__(self, x):

    ...: self.x = x

    ...:

    In [6]: square

    Out[6]: __main__.square

    说这些都是抽象,是因为它们提供了对数据,复合操作或数据集合的封装手段,即将一个名称与复杂的数据或逻辑进行捆绑,使调用者不用关心其实现细节,并且以此来作为构建更复杂的工程的基本元素。可以说绑定是编程的基石。

    回到本文的主题上来,闭包首先是函数,只不过是一种特殊的函数,至于这个特殊性在哪,等稍后引入更多概念后再进行阐述。

    Scope (作用域)

    scope(作用域),顾名思义,也就是某个binding 能罩多大的范围,或者说你可以在多大范围内访问一个变量。每个函数定义会构造一个局部定义域。

    python,和大多数编程语言一样,使用的是静态作用域(static scoping,有时也称 lexical scoping)规则。在函数嵌套定义的时候,内层函数内可以访问外层函数的变量值。因此你可以把作用域想象成一个容器,即它是可以嵌套的,并且内层作用域会扩展外层作用域,而最外层作用域即全局作用域。

    上一小节提到了,多次同名绑定,后面会覆盖前面,其实有隐含前提:在同一作用域内。如果是嵌套作用域,其实是隐藏的关系,内层函数的变量定义会遮蔽外层函数同一名字定义,但是在外层作用域中,该变量仍是原值:

    In [16]: a = 4

    In [17]: def outer():

    ...: a = 5

    ...: print(a)

    ...: def inner():

    ...: a = 6

    ...: print(a)

    ...: inner()

    ...: print(a)

    ...:

    In [18]: outer()

    5

    6

    5

    In [19]: print(a)

    4

    可以看出,作用域其实也可以从另一个角度理解,即我们在某个环境(environment)中,在确定一个name binding 值的时候,会从最内层作用域顺着往外找,找到的第一个该名字 binding 的对应的值即为该 name 引用到的值。

    需要强调的时候,函数的嵌套定义会引起定义域的嵌套,或者说环境扩展(内层扩展外层)关系。类的定义又稍有不同,class 定义会引入新的 namespace,namespace 和 scope 是常拿来对比的概念,但这里按下不表,感兴趣的可以自己去查查资料。

    说到这里,要提一下,一个常被说起的例子:

    In [50]: a = 4

    In [51]: def test():

    ...: print(a) # 这里应该输出什么?

    ...: a = 5

    ...:

    In [52]: test()

    ---------------------------------------------------------------------------

    UnboundLocalError Traceback (most recent call last)

    in ()

    ----> 1 test()

    in test()

    1 def test():

    ----> 2 print(a)

    3 a = 5

    4

    UnboundLocalError: local variable 'a' referenced before assignment

    想象中,上面 print 处应该输出 4 或者 5 才对,为什么会报错呢?这是因为 test 函数在定义时候,分词器会扫一遍 test 函数定义中的所有 token,看到赋值语句 a=5 的存在,就会明确 a 是一个局部变量,因此不会输出4。 而在执行到 print(a) 的时候,在局部环境中,a 还未被binding,因此会报 UnboundLocalError。

    稍微探究一下,虽然 python 是解释执行的,即输入一句,解释一句,执行一句。但是对于代码块(即头部语句,冒号与其关联的缩进块所构成的复合语句(compound sentences),常见的有函数定义,类定义,循环语句等等)来说,还是会整体先扫一遍的。

    First-Class Functions(函数是第一等公民)

    一般来说,组成编程语言的元素,如变量,函数和类,会被设定不同的限制,而具有最少限制的元素,被我们成为该编程语言中的一等公民。而一等公民最常见的特权有:可以被binding到名字上

    可以作为参数在函数中传递

    可以作为返回值被函数作为结果返回

    可以被包含在其他数据结构中

    套用到python中的函数来说来说,即一个函数可以被赋值给某个变量,可以被函数接收和返回,可以定义在其他函数中(即嵌套定义):

    In [32]: def test():

    ...: print('hello world')

    ...:

    In [33]: t = test # 赋值给变量

    In [34]: t()

    hello world

    In [35]: def wrapper(func):

    ...: print('wrapper')

    ...: func()

    ...:

    In [36]: wrapper(t) # 作为参数传递

    wrapper

    hello world

    In [37]: def add_num(a):

    ...: def add(b): # 嵌套定义

    ...: return a + b

    ...: return add # 作为函数的返回值

    ...:

    ...:

    In [38]: add5 = add_num(5)

    In [39]: add5(4)

    Out[39]: 9

    并不是在所有语言中,函数都是一等公民,比如 Java,上面四项权利 Java 中的函数全都没有。

    在这里,能够操作其他函数的函数(即以其他函数作为参数或者返回值的函数),叫做高阶函数。高阶函数使得语言的表达能力大大增强,但同时,也不容易用好。

    Stack Call(栈式调用)

    每个函数调用,会在环境中产生一个栈帧(frame),并且在栈帧中会进行一些绑定,然后压入函数调用栈中。在函数调用结束时,栈帧会被弹出,其中所进行的绑定也被解除,即垃圾回收,局部作用域也随之消亡。

    1

    In [47]: def test():

    ...: x = 4

    ...: print(x)

    ...:

    In [48]: test()

    4

    In [49]: x

    ---------------------------------------------------------------------------

    NameError Traceback (most recent call last)

    in ()

    ----> 1 x

    NameError: name 'x' is not defined

    即在调用结束后,局部定义的变量 x 在外边是访问不到的。但是如之前例子 中,返回的 add函数却引用了已经调用结束的 add_num 中的变量 a,怎么解释这种现象呢?可以记住一条,也是之前提到过的:

    函数嵌套定义时,内部定义的函数所在的环境会自动扩展其定义所在环境

    因此在外部函数返回后,返回的内部函数依然维持了其定义时的扩展环境,也可以理解为由于内部函数引用的存在,外部函数的环境中所有的 bindings 并没有被回收。

    Closure (闭包)

    千呼万唤始出来,以为高潮其实已结束。

    闭包就是建立在前面的这些概念上的,上面提到的某个例子:

    In [37]: def add_num(a):

    ...: def add(b): # 嵌套定义

    ...: return a + b

    ...: return add # 作为函数的返回值

    ...:

    ...:

    In [38]: add5 = add_num(5)

    In [39]: add5(4)

    Out[39]: 9

    其实就是闭包。捡起之前伏笔,给出我对闭包的一个理解:它是一种高阶函数,并且外层函数(例子中的add_num)将其内部定义的函数(add)作为返回值返回,同时由于返回的内层函数扩展了外层函数的环境(environment),也就是对其产生了一个引用,那么在调用返回的内部函数(add5)的时候,能够引用到其(add)定义时的外部环境(在例子中,即 a 的值)。

    结语

    说了这么多,其实只是在逻辑层面或者说抽象层面去解释闭包是什么,跟哪些概念纠缠在一起。但这些其实都不本质,或者说依然是空中楼阁,如果想要真正理解闭包,可以去详细了解下 python 的解释执行机制,当然,那就是编译原理范畴的东西了。

    参考

    展开全文
  • ● bool是int的子类a =Trueprintisinstance(a, int)print True == 1print False == 0运行结果:TrueTrueTrue● 列表循环中的变量泄露#情况一i = 1li= [i for i in range(5)]printi#情况二i = 1for i in range(5):...
  • 首先给出闭包函数的必要条件:闭包函数必须返回一个函数对象闭包函数返回的那个函数必须引用外部变量(一般不能是全局变量),而返回的那个函数内部不一定要return几个典型的闭包例子:#ENV>>> Python 3.6#NO.1...
  • http://mp.weixin.qq.com/s/vS7pICPZm9XQLVuaJTGdzwPython闭包和装饰器是经常涉及的问题,也是比较让人容易进入误区的地方,借此我说一下自己对Python闭包的一些理解 闭包必须有三个条件:必须有一个内嵌函数内嵌...
  • 首先给出闭包函数的必要条件:闭包函数必须返回一个函数对象闭包函数返回的那个函数必须引用外部变量(一般不能是全局变量),而返回的那个函数内部不一定要return几个典型的闭包例子:#ENV>>> Python 3.6#NO.1...
  • Python闭包可能会在面试或者是工作中经常碰到,而提到Python的延迟绑定,肯定就离不开闭包的理解,今天总结下 关于闭包的概念以及一个延迟绑定的面试题。Python闭包1、什么是闭包,闭包必须满足以下3个条件:必须是...
  • 什么是闭包?简单说,闭包就是根据不同的配置信息得到不同的结果。再来看看专业的解释:闭包(Closure)是词法闭包(Lexical Closure)的简称,是...延迟绑定Python闭包函数所引用的外部自由变量是延迟绑定的。Pytho...
  • python 闭包

    2016-09-08 10:28:15
    python 闭包
  • 1、个人理解定义:在一个函数A内部定义一个函数B,并在定义的内部函数B内对这个函数A的变量进行引用,那么内部函数B就是闭包。2、特性:在内部函数内不能对A函数的变量进行更改 (但是可以将其封装到一个容器内,如...
  • python闭包

    2016-04-16 22:46:15
    Python闭包浅析
  • for e in collections:pass在for 循环里, 最后一个对象e一直存在在上下文中。就是在循环外面,接下来对e的引用仍然有效。...for循环不是闭包,可以使用dis模块分解以下代码可以看到:x = 5for x i...
  • 闭包到中间件什么是闭包计算机中的闭包数学领域中的闭包闭包使用场景C/C++ 中的闭包思想C 中类似闭包的结构C++ 中类似闭包的结构python预备知识之变量与作用域python 闭包闭包无法修改自由变量循环闭包配合从...
  • Python 闭包

    2021-01-25 09:47:22
    闭包(closure)作为一个不太容易理解的概念出现在很多主流编程语言中,Python 中很多高级实现都离不开 闭包,装饰器 就是使用 闭包 的典型例子。 作用域 要学习 闭包,先了解 作用域 的概念。 作用域 是程序运行时...
  • Python闭包

    2017-09-26 15:35:35
    举例: # -*-( coding: utf-8 -* def fa(m): ...python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭
  • UnboundLocalError: local variable'a' referenced before assignment 原因: 这是因为在执行代码 c = foo()时,python会导入全部的闭包函数体bar()来分析其的局部变量python规则指定所有在赋值语句左面的变量都是...
  • def count(): fs = [] for i in range(1,4): def f(): return i*i fs.append(f) ... 所以就利用了闭包(嵌套函数)这个东西,因为只能在函数内使用这个变量嘛,所以就在函数内专门创建一个函数来使用这个局部变量 ""

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,764
精华内容 5,105
关键字:

python闭包循环变量

python 订阅