16_Python变量做用域_Python编程之路

 

以前跟你们已经讲了有关函数的一部分知识,可是忘了讲一个很重要的点,就是变量的做用域,这块知识不仅是适用于函数,它试用域全部的Python程序python

在正式写程序以前,必需要清楚这一块,不然就很容易犯错误闭包

 

首先理清一个概念,什么是变量

变量能够咱们能够将它看为指向值的名称,就像咱们以前讲的字典同样的,只是这个字典你是看不到,固然这是很通俗的解释,但也离真相不远了函数

在Python中有一个vars的内置函数,他能够返回这个看不见的“字典”spa

 

好比如下代码blog

In [1]: a = 100

In [2]: distrue = vars()

In [3]: distrue["a"]
Out[3]: 100

In [4]: distrue["a"] += 100

In [5]: a
Out[5]: 200

  是否是很是神奇,把变量变成了一个键值对应的字典,并且还能够经过索引更改值索引

在这里要注意一点,根据官方文档,是不该该修改vars返回的字典的,这样会使得结果不肯定作用域

 

咱们把这种看不见的字典叫作命名空间或者是做用域文档

 

做用域

咱们如今给出如下代码class

In [7]: a = 100

In [8]: def func_one():
   ...:     a = 200
   ...:

In [9]: func_one()

In [10]: a
Out[10]: 100

  一开始,咱们定义了一个变量,将100赋值给了a,而后咱们后面定义了一个方法,将200赋值给a变量

以后,咱们调用了这个方法,可是,最后a的值并无改变,这个就牵涉到有关变量做用域的问题了,咱们慢慢解释

 

首先咱们调用func_one时是建立了一个新的命名空间,以供func_one中的代码块使用,而赋值语句a = 200是在这个函数内部的做用域执行的,也就是一个局部命名空间,他是不会影响外部做用域(或者是全局)的变量,

 

在函数内部使用的变量咱们把它成称为局部变量,在函数外的就称做全局变量

参数是相似于局部变量的,因此他的命名即便与全局变量相同也是没有关系的

 

好比下面的一个输出函数

In [12]: def output(x):
    ...:     print(x)
    ...:

In [13]: x = 10

In [14]: y = 20

In [15]: output(y)
20

In [16]: output(x)
10

  

 

函数访问全局变量

只是读取值得话,很是简单

好比如下代码

In [18]: def linkval(words):
    ...:     print(words + external)
    ...:

In [19]: external = " susmote"

In [20]: linkval("hello")
hello susmote

  可是,在这提醒如下,这种方法仍是慎用,很容易形成bug

 

这个时候,咱们又遇到了一个新的问题,若是局部变量和全局变量相同的话,就会出现遮盖的问题

稍微改一下上面的代码,问题就出现了

In [21]: def linkval(words):
    ...:     external = " jack ma"
    ...:     print(words + external)
    ...:

In [22]: external = " susmote"

In [23]: linkval("hello")
hello jack ma

  也就是说,全局变量被局部变量给遮住了

若是实在有须要的话,可使用globals函数来访问全局变量,他会返回一个包含全局变量的字典,也就是说能够经过字典的键索引获取值

(相对的locals返回一个包含局部变量的值)

 

仍是上面的代码,咱们稍稍作一点改变,结果就会大相径庭

In [24]: def linkval(words):
    ...:     external = " jack ma"
    ...:     print(words + globals()['external'])
    ...:

In [25]: external = " susmote"

In [26]: linkval("hello")
hello susmote

  

 

函数中定义全局变量

通常咱们在函数中定义变量,它默认是局部变量,可是咱们能够直接声明定义的变量为全局变量,这时咱们就必须用到global这个关键词了

In [32]: a = 100

In [33]: def func_one():
    ...:     global a
    ...:     a += 100
    ...:

In [34]: func_one()

In [35]: a
Out[35]: 200

In [36]: func_one()

In [37]: a
Out[37]: 300

  

 

做用域的嵌套

以前有一个概念没有讲到,就是函数的定义是能够嵌套的,相似于一个函数中,还能够定义函数,相似于如下代码

In [45]: def func_one():
    ...:     def func_two():
    ...:         print("内层函数")
    ...:     print("外层函数")
    ...:     func_two()
    ...:

In [46]: func_one()
外层函数
内层函数

  

嵌套函数实际做用并不大,但他的一个突出的功能仍是不错的,使用一个函数来建立另外一个函数

例如如下代码

In [48]: def adder(factor):
    ...:     def addByFactor(number):
    ...:         return number + factor
    ...:     return addByFactor
    ...:
    ...:

In [49]: adder(10)(10)
Out[49]: 20

In [50]: adder(100)(100)
Out[50]: 200

  

一个函数位于另外一个函数中,并且外面的函数返回的是里面的函数,没有调用这个函数

其中,最重要的一点是,返回的函数可以访问其定义所在的做用域,也就是说,他返回时,还带着他本身所在的环境(相关的局部变量)

 

放到实际中来讲就是能够在内部函数中访问这个来自外部做用域的局部变量

咱们把这种函数称之为 闭包

 

若是要给外部做用域的变量赋值,能够用nonlocal关键词,这有点相似于global

 

关于做用域我要讲的就是这些,经过简单的练习,就能很快理解

相关文章
相关标签/搜索