Python初学(7)——Python中的作用域基础

    准备编写函数,我们就需要正式的了解Python中的变量的含义。当在程序中使用变量名时,Python创建、改变或查找变量名都是在所谓的命名空间(一个保存变量名的地方)中进行的。当我们谈论到搜索变量名对应于代码的值的时候,作用域这个术语指的就是命名空间。在代码中变量名被赋予的位置决定了这个变量名能被访问到的范围。

 

    关于所有变量名,包括作用域的定义在内,都是在Python赋值的时候生成的。Python中的变量名在第一次赋值时已经创建,并且经过赋值后才能使用。由于变量名最初没有声明,Python将一个变量名被赋值的地点关联为(绑定给)一个特定的命名空间。也就是说,在代码中给一个变量赋值的地方决定了这个变量将存在于哪个命名空间,也就是它可见的范围。


1,一个在def内定义的变量名能够被def内的代码使用。不能在函数的外部引用这样的变量名。

2,def之中的变量名与def之外的变量名并不冲突。

3,如果一个变量在一个嵌套的def中被赋值,对于嵌套的函数来说,它是非本地的。

4,如果在def之外赋值,它就是整个文件全局的。

 

作用域法则

1,内嵌的模块是全局作用域。

    每个模块都是一个全局作用域(也就是说,一个创建于模块文件顶层的变量的命名空间)。对于外部的全局变量就成为一个模块对象的属性,但是在一个模块中能够像简单的变量一样使用。 

2,全局作用域的作用范围仅限于单个文件。

    别被这里的“全局”所迷惑,这里的全局指的是在一个文件的顶层的变量名仅对于这个文件内部的代码而言是全局的。在Python中是没有基于一个单个的、无所不包的情景文件的全局作用域的。替代这种方法的是,变量名由模块文件隔开,并且必须精确地导入一个模块文件才能够使用这个文件中定义的变量名。当你在Python中听到的“全局的”,你就应该想到“模块”。

 

3,每次对函数的调用都创建了一个新的本地作用域。

    每次调用函数,都创建了一个新的本地作用域。也就是说,将会存在由那个函数创建的变量的命名空间。可以认为每一个def语句(以及lambda表达式)都定义了一个新的本地作用域,但是因为Python允许函数在循环中调用自身(递归)。所以从技术上讲,本地作用域实际上对应的是函数的调用。

 

4,赋值的变量名除非声明为全局变量或者非本地变量,否则均为本地变量。

    在默认情况下,所有函数定义内部的变量名是位于本地作用域(与函数调用相关的)内的。如果需要给一个在函数内部却位于模块文件顶层的变量名赋值,需要在函数内部通过global语句声明。如果需要给位于一个嵌套的def中的名称赋值。从Python3.0开始可以通过在一条nonlocal语句中声明它来做到。

 

5,所有其他的变量名都可以归纳为本地、全局或者内置的。

    在函数定义内部尚未赋值的变量名是一个在一定范围内(在这个def内部)的本地变量、全局(在一个模块的命名空间内部)或者内置(由Python的预定义_builtin_模块提供的)变量。

 

变量名解析:LEGB原则

对于一个def语句:

1,变量名引用分为三个作用域进行查找:首先是本地,之后是函数内,之后全局,最后是内置。

2,在默认情况下,变量名赋值会创建或者改变本地变量。

3,全局声明和非本地声明将赋值的变量名映射到模块文件内部的作用域。

 

global 语句

    global语句是Python中唯一看起来有些像声明语句的语句。但是,它并不是一个类型或大小的声明,它是一个命名空间的声明。它告诉Python函数打算生成一个或多个全局变量。也就是说,存在于整个模块内部的作用域(命名空间)的变量名。


全部变量:

1,全局变量是位于模块内部的顶层的变量名。

2,全局变量如果是在函数内被赋值的话,必须经过声明。

3,全局变量名在函数内部不经过声明也可以被引用。

    换句话说,global允许我们修改一个模块文件的顶层的一个def之外的名称。正如我们将在随后看到的,nonlocal语句几乎是相同的,但是它应用与嵌套的def的被动作用域内的名称,而不是嵌套的模块中的名称。

例子:



    第一个函数中的变量X 前面加global 实际上是引用了外部的X,第二个函数中的X 没有加global,是本地变量,不会改变外部的X的值,外部的X还是88.

嵌套作用域例子:


    函数 f1里面有X变量 外面有关全局的X变量,函数f1里面还实现了一个函数f2,f2打印的X 是f1这个函数体的本地变量X,函数f2是函数f1 的本地函数,是个临时函数。

    所以例子中执行f1 打印的是88 而不是99,这里要注意的是 函数的嵌套在Python中是存在的。但是在C语言中函数的这种嵌套是不允许的。

 

nonlocal语句

    nonlocal语句是和global的近亲,nonlocal和global一样,声明了将要在一个嵌套的作用域中修改的名称。和global不同之处在于,nonlocal应用于一个嵌套的函数作用域中的一个名称,而不是所有的def之外的全局模块作用域;而且在声明的nonlocal名称的时候,它必须已经存在于该嵌套函数的作用域中——它们可能存在与一个嵌套的函数中,并且不能由一个嵌套的def中的第一次赋值创建。

    换句话说,nonlocal即允许对嵌套的函数作用域中的名称赋值,并且把这样的名称作用域查找限制在嵌套的def。直接效果是更加直接和可靠的实现了可更改的作用域信息,对于那些不想要或不需要带有属性的类的程序而言。

 

global和nonlocal语句都在某种程度上限制了查找规则:

1,global使得作用域查找从嵌套的模块的作用域开始。

2,nonlocal限制作用域查找只是嵌套的def,要求名称已经存在那里。作用域查找不会继续到全局或内置作用域。

nonlocal例子:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值