python global、nonlocal、闭包、作用域——第10天


今天工作的内容已经完成,于是在公司学习一下午,遇到的闭包作用域的问题一直想不明白,于是问了我们开发他也看了很久才明白(因为他是做java),然后心里想原来并不是所有人都是聪明的,别人 变成优秀的现在就是因为静下心去研究提升。所以自己想转行煎熬的内心又平静而坚定了。

一、变量闭包作用域

  python的闭包是如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包

def outer():
    x=8
    def inner(y):
        return x + y
    return inner

  下面这个应该是很多人都看过的,但是在我最初看的时候我以为是1,3,9,但是程序运行都是9,debug之后想了好久才明白

  

def count():
    fs = []
    for i in range(1,4):
        def fn():
            return i*i
        fs.append(fn)
    return fs
f1,f2,f3 = count()
print(f1()) #9
print(f2()) #9
print(f3()) #9

因为是fs存了fn这个函数,return i*i 这里的i使用了外部函数for循环里面的i,当调用fn函数的时候,for i 里面的i已经循环变成3, fn函数执行的时候去找变量i是i=3的,所以就都是9

想要把上边的结果变成1,4,9可以使用如下方法:

def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f(),每一次的i都会指向一个g的内容地址
    return fs

f1,f2,f3 = count()
print(f1()) #1
print(f2()) #4
print(f3()) #922:40:53

下面的代码会报错:UnboundLocalError: local variable 'a' referenced before assignment

a = 10
def bar():
    print(a)
    a = 'in bar'
bar()

报错的原因是因为python编译的时候发现a局部变量是这样子定义的a = ,没有赋值。

在上面的函数bar中在执行第一条语句的时候,为什么不去访问全局变量a呢这是Python语法的规定,当在函数体中有赋值语句的时候,编译的时候就认为定义了局部变量,从而保证函数封装性

二、global

想要前面的值不报错可以使用global关键字

a = 10
def bar():
    global a
    a = 'in bar'
bar()
print(a) #in bar

但是使用这种代码得小心了,他很容易改变全局变量的值

三、nonlocal

闭包

def fn():
    count = 8
    def inner(dt=0):
        r =count +dt
        print(r) #8
    return inner
fn()()

如果上面的代码改动一点点他就会报上面的错:UnboundLocalError: local variable 'a' referenced before assignment,原理是和之前一样的

def fn():
    count = 8
    def inner(dt=0):
        count+=dt
        print(count) 
    return inner
fn()() #会报错

如果想要上面的代码不报错可以使用nonlocal关键字如下:

def fn():
    count = 8
    def inner(dt=0):
        nonlocal count
        count =count +dt
        print(count)
    return inner
fn()() #8

nonlocal关键字使用是,内部函数的变量没有时,可以到外部函数寻找变量。

但是值得注意的是使用nonlocal关键字时,内部函数的变量改变了外部函数的变量也会改变,如下:

name = 'global'
def test():
    name = 'local'

    def inner_test():
        nonlocal name
        # global name

        name = name + '变量'
        return name

    print(name) #'local'+'变量'
    return inner_test()

print(name) #'global'
print(test())
print(name) #'global'
def funX():
    x =5
    def funY():
        nonlocal x
        x+=1
        return x
    return funY
a = funX()
print(a()) #6
print(a()) #7 因为x+=1已经把外部函数的x改成了6
print(a()) #8

所以我感觉global和nonlocal还是少用的好

                        ——————一条薛定谔的咸鱼

优质内容筛选与推荐>>
1、博客园配置window live write最新说明
2、蓝桥杯入门训练——圆的面积(保留小数位)
3、20155238 2016-2017-2 《Java程序设计》第三周学习总结
4、springMVC 报错:Unknown return value type: java.lang.Integer
5、量化自己的大学生活


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn