嵌套函数变量引用问题

nonlocal的作用:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

 

首先我们要清楚:变量引用的规则

函数内部嵌套函数时,最内层的函数引用某一个变量时(x),先在本层函数中寻找有没有之前对该变量(x)的定义,如果有直接引用,如果没有则会在该层函数的上一层中寻找。如果还没有就依次向上层寻找。

当弄清了上面所述的,我们来看下面的四个程序test1test1_atest1_btest1_c

名称

test1

 test1_a

test1_b

test1_c

def func():
    x = 200

    def func2():
        print(x)
    func2()

 

func()

def func():

    x = 200

    def func2():
        x=x
        print(x)
    func2()

 

func()

 

 

def func():
    x = 200

    def func2():
        nonlocal x
        x=x
        print(x)
    func2()

func()

def func():
    x = 200

    def func2():
        y=x
        print(y)
    func2()

func()

执行

结果

 200 报错

UnboundLocalError:

local variable 'x'

referenced before

assignment

 200  200

 

test1

nonlocal的作用: 随笔 第1张
def func():
    x = 200

    def func2():
        print(x)
    func2()


func()
test1

 

test1_a

nonlocal的作用: 随笔 第3张
def func():
    x = 200

    def func2():
        x=x
        print(x)
    func2()


func()
test1_a

 

test1_b

nonlocal的作用: 随笔 第5张
def func():
    x = 200

    def func2():
        nonlocal x
        x=x
        print(x)
    func2()

func()
test1_b

 

test1_c

nonlocal的作用: 随笔 第7张
def func():
    x = 200

    def func2():
        y=x
        print(y)
    func2()


func()
test1_c

 

 

首先test1程序的结果验证了我们上述的变量引用规则,func2中的语句print(x)对变量x进行打印,由于本层函数func2中没有定义x所以在func2的上层寻找,找到了func中的x=200,于是func打印的x值为200

我们再来看test1_a这个程序,内层函数func2中有一个语句x=x第一个x是变量的定义(这时说明本层函数定义了一个变量x),第二个x就需要寻找引用值了,现在本层函数中寻找,这就找到了刚刚定义的变量x,也就时第一个x。相当与定义后面承接着引用,这就会产生一个问题:变量x实际上是没有值的,所以程序会报错。

test1_b中内层函数func2在执行x=x语句时,用nonlocal x这个语句声明了x引用的范围(跳过本层的引用),也就在后面执行x=x这一语句时,第二个x不再引用第一个x,跳过了本层的引用,引用了上一层的 x = 200,再把这个x赋给本层定义的x,最后程序的结果就是200

我们再来通过test1_atest1_c来对比分析,可以看到test1_c中内层函数func2中定义的变量换成了y,这就使得后面的x在引用时由于在本层找不到定义的x,所以就接着到上层寻找。

test1_btest1_c比较可以发现,在遇到嵌套函数变量引用的问题时,除了通过使用nonlocal x 语句使得x跳过本层寻找外,还可以通过跟换本层定义的变量名,使得x再寻找引用时由于本层没有对x的定义而跳至上层寻找。

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄