python 的全局变量和局部变量

首先我们看一段代码,是不是有很多疑惑

def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

'''
输出:
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
'''

一直看不明白第三个为什么时这样,补充一下

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

我们忘记了,如果局部变量与全局变量变量名一样,则优先调用局部变量,因此上面的难题解决了

 

首先我们先了解全局变量和局部变量

 

1.全局变量和局部变量的区别在于作用域,全局变量在整个py文件中声明,全局范围内可以使用;局部变量是在某个函数内部声明的,只能在函数内部使用,如果超出使用范围(函数外部),则会报错

A = 100 # 全局变量一般用大写字母表示
def func():
    a = 50 # 局部变量一般用小写字母表示
    print(a+A)

func()  #150
print(A)  #100
print(a) # 报错信息NameError: name 'a' is not defined,说明局部变量只能在函数内使用

 

2.在函数内部,如果局部变量与全局变量变量名一样,则优先调用局部变量

A = 100
def func():
    A=250
    print(A)


print(A)    # 打印全部变量  100
func()      # 局部变量  250

 

3.如果想在函数内部改变全局变量,需要在前面加上global关键字,在执行函数之后,全局变量值也会改变

A = 100

def func():
    global  A
    A = 200
    print(A)


print(A)    # 打印全局变量 100
func()      # 局部变量  200
print(A)   # 改变后的全局变量  200

 

4.如果全局变量是列表类型(针对全局变量如果是可变对象,可以对内部元素进行操作),可以通过list的列表方法去对列表进行修改,并且可以不用global来声明

list_1 = [1,2,56,"list"]

def changeList():
    list_1.append("over")
    print(list_1)

changeList()  #[1, 2, 56, 'list', 'over']
print(list_1)  #[1, 2, 56, 'list', 'over']

 

5.如果函数中有global关键字,变量本质上就是全局变量,可读取可赋值

NAME = "nicholas"
print(1,NAME)
def change_NAME():
    global NAME
    NAME = "niubi"
    print("change_NAME", NAME)
change_NAME()
print(2,NAME)  #有global,定义的就是全局变量,可以赋值以及修改

要注意global的位置,如果需要global对全局变量进行修改这里的global不能放在name = "nick"下面

 

 

6.如果全局变量是不可变对象(非list)等,我们就不能在函数里面去修改全局变量,但是我们想修改,那么就可以使用global

count = 0
def global_test():
    count += 1
    print(count)
global_test()  #UnboundLocalError: local variable 'count' referenced before assignment

 

nonlocal

python变量引用顺序:从当前作用域开始寻找变量,如果没找到就往上一层作用域寻找,没找到就再上一层......

即:当前作用域局部变量->外层作用域变量->再外层作用域变量->......->当前模块全局变量->pyhton内置变量

global:全局变量

nonlocal:外层嵌套函数的变量

使用总结:

1、局部作用域改变全局变量用global, global同时还可以定义新的全局变量

2、内层函数改变外层函数变量用nonlocal, nonlocal不能定义新的外层函数变量,只能改变已有的外层函数变量(外层直到全局作用域的下一层都没有,会报错),同时nonlocal不能改变全局变量

当没有nonlocal时

a = 10  # a1 当前模块全局变量
def outer():
    a = 9  # a2 当前outter作用域局部变量
    def inner():
        a = 8  # a3 当前inner作用域局部变量
        print(a)  # a3 8, 在inner的局部作用域中找到了a3
    inner()  # inner()函数结束,a3作为inner局部变量被释放
    print(a)  # a2 9,在outer局部作用域中找到a2
outer()  # outer()函数结束,a2作为outer局部变量被释放
a
'''
8
9
10
'''

 

用于在内层函数中改变外层函数变量

a = 10  # a1 当前模块全局变量
def outer():
    a = 9 # a2 outer局部变量
    def inner():
        nonlocal a
        a = 8  # a3  既是inner局部变量,又是外层outer局部变量
        print(a)  # a3 8,在inner的局部作用域中找到了a3
    inner()  # inner()函数结束,a3作为外层变量(outer局部变量)被保留成为a2
    print(a)  # a2 8,在outer局部作用域中找到a2(在inner中被改变)
outer()  # outer()函数结束,a2作为outer局部变量被释放
print(a)  # a1 10,在当前模块全局作用域中找到了a1

'''
输出
8
8
10
'''

 

如果在外层没有找到变量a,则会继续在再外层寻找,直到全局作用域的下一层为止

a = 10  # a1 当前模块全局变量
def outer2():
    a = 9 # a2 outer2作用域局部变量
    print(a) # a2 9,还未被a3改变
    def outer1():
        print(a) # a2 9,在outer1中没找到局部变量a,则寻找外层(outer2)变量a2(还未被a3改变)
        def inner():
            nonlocal a
            a = 0  # a3 既是inner局部变量,又是再外层outer2作用域变量
            print(a)  # a3 0, 找到inner局部变量a3
        inner()  # inner()函数结束,a3作为外层变量(outer2局部变量)被保留成为a2
        print(a)  # a2 0,在outer1中没找到局部变量a,则寻找外层(outer2)变量a2(被a3改变)
    outer1()
    print(a) # a2 0, 在outer1中找到outer1局部变量a2(被a3改变)
outer2() 
print(a)  # a1 10,在当前模块全局作用域中找到了a1

'''
输出
9
9
0
0
0
10
'''

 

全局变量不是外层变量,不被nonlocal寻找

a = 10  # a1 当前模块全局变量
def outer():
    def inner():
        nonlocal a  # 在当前作用域外层即outer局部作用域中没找到outer局部变量a,outer外层为全局作用域,nonlocal不继续寻找,报错
        a = 8
        print(a)
    inner()
    print(a)
outer() 
print(a)  # a1 10,在当前模块全局作用域中找到了a1

'''
输出
SyntaxError: no binding for nonlocal 'a' found
'''

注意:使用global关键字修饰的变量之前可以并不存在,而使用nonlocal关键字修饰的变量在嵌套作用域中必须已经存在

 

posted on 2020-12-28 23:25  小小喽啰  阅读(1387)  评论(0编辑  收藏  举报