print(v)NameErr" />

python变量与作用域

系统 1612 0

变量从作用域分类

作用范围从小到大为,小作用域的可以调用大作用域的内容。

  • 局部 Local
  • 闭包 Enclosing
  • 全局 Global
  • 内建 Build-in

局部变量

局部变量是定义在函数中的,因此其作用域是在函数内部。

            
              
                def
              
              
                example
              
              
                (
              
              
                )
              
              
                :
              
              
    v
              
                =
              
              
                1
              
              
                #局部变量
              
              
                print
              
              
                (
              
              v
              
                )
              
            
          

由于局部变量作用域只在函数内部有效,因此程序会报错

            
              Traceback 
              
                (
              
              most recent call last
              
                )
              
              
                :
              
              
  File 
              
                "test.py"
              
              
                ,
              
               line 
              
                3
              
              
                ,
              
              
                in
              
              
                <
              
              module
              
                >
              
              
                print
              
              
                (
              
              v
              
                )
              
              
NameError
              
                :
              
               name 
              
                'v'
              
              
                is
              
              
                not
              
               defined

            
          

全局变量

和局部变量相对,全局变量是定义在函数外的变量,因此具有更大的作用域。

            
              v
              
                =
              
              
                1
              
              
                def
              
              
                example
              
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              v
              
                )
              
              
example
              
                (
              
              
                )
              
            
          

运行结果

            
              
                1
              
            
          

注意事项
python与C有许多不同的地方
(1)例子1

            
              v
              
                =
              
              
                1
              
              
                def
              
              
                example
              
              
                (
              
              
                )
              
              
                :
              
              
    v
              
                =
              
              
                2
              
              
                print
              
              
                (
              
              v
              
                )
              
              
example
              
                (
              
              
                )
              
              
                print
              
              
                (
              
              v
              
                )
              
            
          

运行结果

            
              
                2
              
              
                1
              
            
          

当想要在函数中对全局变量进行赋值时,如上操作,python会生成新的局部变量,而不是修改全局变量的值,可以通过global标记在局部作用域中声明全局变量。

            
              v
              
                =
              
              
                1
              
              
                def
              
              
                example
              
              
                (
              
              
                )
              
              
                :
              
              
                global
              
               v
    v
              
                =
              
              
                2
              
              
                print
              
              
                (
              
              v
              
                )
              
              
example
              
                (
              
              
                )
              
              
                print
              
              
                (
              
              v
              
                )
              
            
          

运行结果

            
              
                2
              
              
                2
              
            
          

(1)例子2

            
              
                def
              
              
                example
              
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              v
              
                )
              
              
    
v
              
                =
              
              
                1
              
              
example
              
                (
              
              
                )
              
            
          

运行结果

            
              
                1
              
            
          

由于python是解释性语言,不需要进行编译,程序运行时每次读源文件的一行代码,并执行相应的操作,因此上述代码可以正常运行,不会出现找不到变量v的问题。而当我们使用如下代码则会报错。

            
              
                def
              
              
                example
              
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              v
              
                )
              
              

example
              
                (
              
              
                )
              
              
v
              
                =
              
              
                1
              
            
          

运行结果

            
              Traceback 
              
                (
              
              most recent call last
              
                )
              
              
                :
              
              
  File 
              
                "test.py"
              
              
                ,
              
               line 
              
                4
              
              
                ,
              
              
                in
              
              
                <
              
              module
              
                >
              
              
    example
              
                (
              
              
                )
              
              
  File 
              
                "test.py"
              
              
                ,
              
               line 
              
                2
              
              
                ,
              
              
                in
              
               example
    
              
                print
              
              
                (
              
              v
              
                )
              
              
NameError
              
                :
              
               name 
              
                'v'
              
              
                is
              
              
                not
              
               defined

            
          

闭包

在python中“一切皆对象”,因此函数也被看作对象,因此产生了一种特殊的形式函数嵌套。如下例子

            
              
                def
              
              
                out_func
              
              
                (
              
              
                )
              
              
                :
              
              
    a 
              
                =
              
              
                1
              
              
    b 
              
                =
              
              
                2
              
              
                def
              
              
                iner_func
              
              
                (
              
              
                )
              
              
                :
              
              
                return
              
               a 
              
                +
              
              
                1
              
              
                return
              
               iner_func

            
          

闭包是在内嵌函数生成的时候将其用到的环境以及自己本身都封装在了一起。为了直观理解闭包,我们介绍一下 code 对象, code 对象是指代码对象,表示编译成字节的的可执行Python代码,或者字节码。它有几个比较重要的属性:

  • co_name: 函数的名称
  • co_nlocals: 函数使用的局部变量的个数
  • co_varnames: 一个包含局部变量名字的元组
  • co_cellvars: 是一个元组,包含嵌套的函数所引用的局部变量的名字
  • co_freevars: 是一个元组,保存使用了的外层作用域中的变量名
  • co_consts: 是一个包含字节码使用的字面量的元组

有如下程序

            
              
                def
              
              
                out_func
              
              
                (
              
              
                )
              
              
                :
              
              
    a 
              
                =
              
              
                1
              
              
    b 
              
                =
              
              
                2
              
              
    c 
              
                =
              
              
                3
              
              
                def
              
              
                iner_func1
              
              
                (
              
              
                )
              
              
                :
              
              
                return
              
               a 
              
                +
              
              
                1
              
              
                def
              
              
                iner_func2
              
              
                (
              
              
                )
              
              
                :
              
              
                return
              
               b 
              
                +
              
              
                1
              
              
                return
              
               iner_func1

func
              
                =
              
              out_func
              
                (
              
              
                )
              
              
                print
              
              
                (
              
              out_func
              
                .
              
              __code__
              
                .
              
              co_varnames
              
                )
              
              
                print
              
              
                (
              
              out_func
              
                .
              
              __code__
              
                .
              
              co_cellvars
              
                )
              
              
                print
              
              
                (
              
              out_func
              
                .
              
              __code__
              
                .
              
              co_freevars
              
                )
              
              
                print
              
              
                (
              
              func
              
                .
              
              __code__
              
                .
              
              co_varnames
              
                )
              
              
                print
              
              
                (
              
              func
              
                .
              
              __code__
              
                .
              
              co_cellvars
              
                )
              
              
                print
              
              
                (
              
              func
              
                .
              
              __code__
              
                .
              
              co_freevars
              
                )
              
            
          

运行结果

            
              
                (
              
              
                'c'
              
              
                ,
              
              
                'iner_func1'
              
              
                ,
              
              
                'iner_func2'
              
              
                )
              
              
                (
              
              
                'a'
              
              
                ,
              
              
                'b'
              
              
                )
              
              
                (
              
              
                )
              
              
                (
              
              
                )
              
              
                (
              
              
                )
              
              
                (
              
              
                'a'
              
              
                ,
              
              
                )
              
            
          

前三个输出是关于外部函数的一些属性,由于out_func函数中声明了几个局部变量,因此包含三个变量。第二个输出是内部的函数用到的变量,而iner_func1与iner_func2用到了变量a与b。第三个输出是使用了的外部作用域的变量,因此是空。
后三个输出是关于内部函数的一些属性,前两个输出由于iner_func1没有使用到因此为空,由于iner_func1用到了外部变量a,因此只有变量a。

若是采用三层的嵌套

            
              
                def
              
              
                outout_func
              
              
                (
              
              
                )
              
              
                :
              
              
    c 
              
                =
              
              
                3
              
              
                def
              
              
                out_func
              
              
                (
              
              
                )
              
              
                :
              
              
        a 
              
                =
              
              
                1
              
              
        b 
              
                =
              
              
                2
              
              
                def
              
              
                iner_func
              
              
                (
              
              
                )
              
              
                :
              
              
                return
              
               a 
              
                +
              
              
                1
              
              
                +
              
               c
        
              
                return
              
               iner_func
    
              
                return
              
               out_func
              
                (
              
              
                )
              
              

func
              
                =
              
              outout_func
              
                (
              
              
                )
              
              
                print
              
              
                (
              
              func
              
                .
              
              __code__
              
                .
              
              co_varnames
              
                )
              
              
                print
              
              
                (
              
              func
              
                .
              
              __code__
              
                .
              
              co_cellvars
              
                )
              
              
                print
              
              
                (
              
              func
              
                .
              
              __code__
              
                .
              
              co_freevars
              
                )
              
            
          

运行结果

            
              
                (
              
              
                )
              
              
                (
              
              
                )
              
              
                (
              
              
                'a'
              
              
                ,
              
              
                'c'
              
              
                )
              
            
          

在学习闭包的过程中,我个人对一下几种情况有点蒙圈。
程序一

            
              f 
              
                =
              
              
                [
              
              
                ]
              
              
v 
              
                =
              
              
                [
              
              
                0
              
              
                ]
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
    v
              
                [
              
              
                0
              
              
                ]
              
              
                =
              
               i
    
              
                def
              
              
                b
              
              
                (
              
              
                )
              
              
                :
              
              
        x 
              
                =
              
               v
        
              
                return
              
               x
    f
              
                .
              
              append
              
                (
              
              b
              
                )
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              f
              
                [
              
              i
              
                ]
              
              
                (
              
              
                )
              
              
                )
              
              
                print
              
              
                (
              
              
                id
              
              
                (
              
              f
              
                [
              
              i
              
                ]
              
              
                (
              
              
                )
              
              
                )
              
              
                )
              
            
          

运行结果

            
              
                [
              
              
                4
              
              
                ]
              
              
                1618988720712
              
              
                [
              
              
                4
              
              
                ]
              
              
                1618988720712
              
              
                [
              
              
                4
              
              
                ]
              
              
                1618988720712
              
              
                [
              
              
                4
              
              
                ]
              
              
                1618988720712
              
              
                [
              
              
                4
              
              
                ]
              
              
                1618988720712
              
            
          

程序二

            
              f
              
                =
              
              
                [
              
              
                ]
              
              
v
              
                =
              
              
                [
              
              
                0
              
              
                ]
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
                def
              
              
                b
              
              
                (
              
              
                )
              
              
                :
              
              
        x
              
                =
              
              v
        v
              
                [
              
              
                0
              
              
                ]
              
              
                =
              
              i
        
              
                return
              
               x
    f
              
                .
              
              append
              
                (
              
              b
              
                )
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              f
              
                [
              
              i
              
                ]
              
              
                (
              
              
                )
              
              
                ,
              
              
                id
              
              
                (
              
              f
              
                [
              
              i
              
                ]
              
              
                (
              
              
                )
              
              
                )
              
              
                )
              
            
          

运行结果

            
              
                [
              
              
                0
              
              
                ]
              
              
                1397297537608
              
              
                [
              
              
                1
              
              
                ]
              
              
                1397297537608
              
              
                [
              
              
                2
              
              
                ]
              
              
                1397297537608
              
              
                [
              
              
                3
              
              
                ]
              
              
                1397297537608
              
              
                [
              
              
                4
              
              
                ]
              
              
                1397297537608
              
            
          

两个程序类似,但是输出完全不同。

第一个程序之所以输出全是相同的,是因为在闭包生成的过程中打包了 v 的地址作为闭包环境。在函数调用时将 x 指向了相同的地址,也就是 v 的地址,而在函数调用之前, v 进行了5次赋值,最后一次被赋为了4,因此每次的输出均相同。

第二个程序之所以输出不同,是因为闭包在生成过程中将 v 的地址以及 i 的地址都打包了,而 i 指向的是常数,因此具有不同的地址。所以当函数运行时, x 先指向了 v 的地址,之后 v 中的数字被替换为 i 指向的不同常量,因此具有不同的输出。

在这里若我们将 i 替换为列表会发生什么呢,有如下程序

            
              f
              
                =
              
              
                [
              
              
                ]
              
              
ha
              
                =
              
              
                [
              
              
                0
              
              
                ]
              
              
z
              
                =
              
              
                [
              
              
                0
              
              
                ]
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
    z
              
                [
              
              
                0
              
              
                ]
              
              
                =
              
              i
    
              
                def
              
              
                b
              
              
                (
              
              
                )
              
              
                :
              
              
        x
              
                =
              
              ha
        ha
              
                [
              
              
                0
              
              
                ]
              
              
                =
              
              z
              
                [
              
              
                0
              
              
                ]
              
              
                return
              
               x
    f
              
                .
              
              append
              
                (
              
              b
              
                )
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              f
              
                [
              
              i
              
                ]
              
              
                (
              
              
                )
              
              
                ,
              
              
                id
              
              
                (
              
              f
              
                [
              
              i
              
                ]
              
              
                (
              
              
                )
              
              
                )
              
              
                )
              
            
          

运行结果

            
              
                [
              
              
                4
              
              
                ]
              
              
                2863541936712
              
              
                [
              
              
                4
              
              
                ]
              
              
                2863541936712
              
              
                [
              
              
                4
              
              
                ]
              
              
                2863541936712
              
              
                [
              
              
                4
              
              
                ]
              
              
                2863541936712
              
              
                [
              
              
                4
              
              
                ]
              
              
                2863541936712
              
            
          

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论