目录

 

一、变量作用域

二、全局变量&局部变量

2.1 global 和nonlocal关键字


一、变量作用域

python中,变量不是在哪里都可以访问的,访问权限决定于变量是在哪里被赋值的。变量作用域决定了哪一部分程序可以访问哪些特定的变量。python的作用域一共分为四种:

  • L(local)  局部作用域
  • E(enclosing)  闭包函数外的函数中
  • G(global) 全局作用域
  • B(built-in)   内建作用域

程序查找变量的规则为:L-->E-->G-->B ,通过位置怎么去判断变量属于那种变量,请看下代码:

x=range(0,10) #内建作用域
spam=10   #全局作用域
def outer():
    eggs=10   # 闭包函数外的函数中
    def inner():
        apple=2   #局部作用域

那什么时候程序会引入新的作用域呢?python中只有类、模块、函数才会引入新的作用域。其他的代码块(如 if/elif/else , for/while)等是不会引入新的作用域的,语句内定义的变量,外部也可以访问,如下代码:

if True:
    msg='hello world'
print(msg) #hello world

这段代码,变量msg在if语句块中,但是外部也可以访问。

二、全局变量&局部变量

全局变量:变量定义在函数外部。全局作用域,是程序开始的时候创建的,程序终止,全局作用域就会被销毁,它的所有变量就会被丢弃。

局部变量:变量定义在函数内部。函数被调用,或者被另一个函数调用时,局部作用域就创建了,该函数返回时,局部作用域就会被销毁。

两者之间的关系:全局作用域中程序不能使用局部作用域中的变量,但是局部作用域中可以使用全局变量。同时局部作用域不可以使用其他局部作用域中的变量。

请看实例:

def spam():
    eggs=99
    bacon()
    print(eggs)
def bacon():
    ham=101
    eggs=0
spam() #99

实例分析:为什么输出的是99而不是0呢?

在程序开始运行时, spam()函数被调用, 创建了一个局部作用域。局部变量eggs被赋值为 99。然后 bacon()函数被调用, 创建了第二个局部作用域。多个局部作用域能同时存在。在这个新的局部作用域中, 局部变量 ham 被赋值为 101。局部变量 eggs(与 spam()的局部作用域中的那个变量不同) 也被创建, 并赋值为 0。当 bacon()返回时, 这次调用的局部作用域被销毁。程序执行在 spam()函数中继续, 打印出 eggs 的值。因为 spam()调用的局部作用域仍然存在, eggs 变量被赋值为 99。

要点在于,一个函数中的局部变量完全与其他函数中的局部变量分隔开来。

 

2.1 global 和nonlocal关键字

  当局部作用域想要修改全局作用域中的变量时,就需要用到global和nonlocal关键字了。

    如果要修改全局变量,要用到global管家字:

#全局变量可以在局部变量中读取
def spam():
    global eggs
    print(eggs)
    eggs=10
    print(eggs)
eggs=42
spam() # 42 10

如果要修改嵌套作用域(enclosing作用域,就是外层的非全局作用域)则需要nonlocal关键字,如下:

def outer():
    num=10
    def inner():
        nonlocal num #nonlocal关键字声明
        num=99
        print(num)
    inner()
    print(num)
outer() # 99 99

还有一种情况,通过参数传递来使用全局变量,如下实例:

a=10
def test():
    a=a+1
    print(a)
test()

运行后会报错:

Traceback (most recent call last):
  File "E:/IdeaProjects/Demi/20180904-1.py", line 151, in <module>
    test()
  File "E:/IdeaProjects/Demi/20180904-1.py", line 149, in test
    a=a+1
UnboundLocalError: local variable 'a' referenced before assignment

报错为局部作用域引用错误。但是可以将全局变量a作为参数传入到test函数中,如下:

a=10
def test(a):
    a=a+1
    print(a)
test(a) #11

输出就是11了。