Python中的global全局变量与nonlocal局部变量

    在Python中,当引用一个变量的时候,对这个变量的搜索是按找本地作用域(Local)、嵌套作用域(Enclosing function locals)、全局作用域(Global)、内置作用域(builtins模块)的顺序来进行的,即所谓的LEGB规则。 即

python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量

    然而当在一个函数内部为一个变量赋值时,并不是按照上面所说LEGB规则来首先找到变量,之后为该变量赋值。在Python中,在函数中为一个变量赋值时,有下面这样一条规则:

当在函数中给一个变量名赋值是(而不是在一个表达式中对其进行引用),Python总是创建或改变本地作用域的变量名,除非它已经在那个函数中被声明为全局变量.


一、 global

global关键字用来在函数或其他局部作用域中使用全局变量。

①如果不修改全局变量,只是引用全局变量,也可以不使用global关键字。

②如果在局部要对全局变量修改,需要在局部也要先声明该全局变量。


gcount = 0   #定义了一个全局变量,(可以省略global关键字)

def global_test():
    print (gcount)    #不修改,只是引用全局变量,不使用global关键字
    
def global_counter():
    global gcount    
    gcount +=1       #修改全局变量,需要使用global关键字
    return gcount
	


二、nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。

def make_counter(): 
    count = 0     #定义一个局部变量,该局部变量作用范围在make_counter()方法内
    def counter(): 
        nonlocal count   #在方法counter()中使用外层局部变量 count 
        count += 1 
        return count 
    return counter 
       
def make_counter_test(): 
  mc = make_counter() 
  print(mc())
  print(mc())
  print(mc())
 
make_counter_test()	

输出:

1
2

3

三、golbal全局变量和nonlocal局部变量
全局变量是针对整个.py文件而言

外层局部(非全局)变量是针对内层方法而言

①在函数中也可以定义全局变量:

函数内部以global定义的变量,表明其作用域在局部以外,即局部函数执行完之后,不销毁。

def add_a():
    global  a
    a =   3
add_a()
print(a)   

输出:3


②在函数 make_counter() 内 定义的global 变量 count,只能在 函数 make_counter() 内引用, 如果要在counter() 内修改,必须在 counter()函数里面声明 global  count,表明是修改外面的 全局变量 count 

def make_counter(): 
    global count      #定义一个全局变量
	count = 0 
    def counter(): 
        global count   #在方法counter()中修改全局变量 count ,要先声明
        count += 1 
        return count 
    return counter 
       
def make_counter_test(): 
  mc = make_counter() 
  print(mc())
  print(mc())
  print(mc())
 
make_counter_test()


最后一个例子:

def scope_test():
    def do_local():
        spam = "local spam"  # 此函数定义了另外的一个spam字符串变量,并且生命周期只在此函数内。此处的spam和外层的spam是两个变量,如果写出spam = spam + “local spam” 会报错

    def do_nonlocal():
        nonlocal  spam  # 使用外层的spam变量
        print("声明的 nonlocal spam id",id(spam))     #未赋值前(spam id 139905931633200)
        spam = "nonlocal spam"
        print("do_nonlocal() nonlocal spam id", id(spam))   #赋值后,重新分配新的地址(spam id 139905931633008)
        print("*" * 20)


    def do_global():
        global spam      #声明一个global 全局变量
        spam = "global spam"
        print("do_global() global spam id", id(spam))   #spam id 139905931633136
        print("*" * 20)

    def do_test():
       # spam = "hahaha"
        print("do_test spam and spam id:",spam,id(spam))  #按照变量引用顺序,应该是nonlocal

    spam = "test spam"   #外层局部变量
    print("spam id:",id(spam))    #(spam id: 139905931633200)
    print("*" * 20)

    do_local()
    print("After local assignmane:", spam)
    print("After local assignmane spam id:", id(spam))
    print("*"*20)

    do_nonlocal()
    print("After nonlocal assignment:", spam)
    print("After nonlocal assignment spam id:", id(spam))
    print("*" * 20)

    do_global()
    print("After global assignment:", spam)  #do_global()已经执行完,按引用变量顺序,调用外层局部变量,前面do_nonlocal()已经执行,此处应为新的外层变量地址
    print("After global assignment spam id:", id(spam))   #(spam id: 139905931633008)
    print("*" * 20)

    do_test()



scope_test()
print("In global scope:", spam)    #此时打印的是do_global()中申明的全局变量,do_global()方法执行完后,全局变量没有被销毁
print("In global scope id:", id(spam))  #(spam id:  139905931633136)

输出:

spam id: 139905931633200
********************
After local assignmane: test spam
After local assignmane spam id: 139905931633200
********************
声明的 nonlocal spam id 139905931633200
do_nonlocal() nonlocal spam id 139905931633008
********************
After nonlocal assignment: nonlocal spam
After nonlocal assignment spam id: 139905931633008
********************
do_global() global spam id 139905931633136
********************
After global assignment: nonlocal spam
After global assignment spam id: 139905931633008
********************
do_test spam and spam id: nonlocal spam 139905931633008
In global scope: global spam
In global scope id: 139905931633136

你可能感兴趣的:(python)