zoukankan      html  css  js  c++  java
  • 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还是少用的好

                           

  • 相关阅读:
    操作系统知识
    接下来 的 重点 是 运维
    并行计算 排序 是 分布式数据库 能否 突破 传统 数据库 性能 瓶颈 的 关键
    并行计算 是 趋势
    高并发 分布式 架构 的 几大 基本要素
    堆栈趣话
    虚拟机 操作系统 容器
    Lambda 表达式 是 个 好东东
    update set from 语句用法 delete 多表删除的使用 以及异常:table name "temp_new_tel" specified more than once
    我的面试
  • 原文地址:https://www.cnblogs.com/venvive/p/11291742.html
Copyright © 2011-2022 走看看