You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改外层函数变量?Python2.7测试Mark Lutz内容遇报错

解决Python 2.7嵌套函数中的UnboundLocalError问题

Mark Lutz在《Learning Python》中提到:“函数可自由使用语法嵌套函数及全局作用域中定义的名称,但修改这些非局部和全局名称必须进行声明”。

你在Python 2.7里碰到的这个UnboundLocalError,其实是Python作用域规则在“搞事情”,咱们一步步拆解清楚:

先看你的报错代码:

def f1():
    f1_a = 'f1_a'
    def f2():
        # global f1_a
        # nonlocal f1_a
        f2_a = 'f2_a'
        print 'f2_a={:s}'.format(f2_a)
        print 'f1_a={:s}'.format(f1_a)
        f1_a = 'f1f2_a'
    f2()
    print 'f1_a={:s}'.format(f1_a)

>>> f1()
# 报错:UnboundLocalError: local variable 'f1_a' referenced before assignment

为啥会报错?

Python的变量查找逻辑很直接:只要你在函数内部给某个变量赋值,Python就会默认这个变量是该函数的局部变量——哪怕外部嵌套作用域里有同名变量。在你的f2函数里,后面有f1_a = 'f1f2_a'这行赋值代码,所以Python直接把f1_a认定为f2的局部变量。但你在赋值之前先尝试print f1_a,这时候局部的f1_a还没被定义,自然就抛出“引用前未绑定”的错误了。

另外要提一句:nonlocal关键字是Python 3才引入的语法,Python 2.7根本不支持,所以你注释掉的那行就算解开也会报语法错误;而global是用来声明全局变量的,这里的f1_a是f1函数的局部变量,不是全局的,所以global也解决不了问题。

Python 2.7里的解决办法

既然Python 2没有nonlocal,咱们可以用两个变通方案绕开这个限制:

方案1:用可变对象包裹变量

把f1_a放到列表(或字典)里,因为列表是可变对象,修改它的元素不需要声明作用域:

def f1():
    f1_a = ['f1_a']  # 用列表包裹变量
    def f2():
        f2_a = 'f2_a'
        print 'f2_a={:s}'.format(f2_a)
        print 'f1_a={:s}'.format(f1_a[0])
        f1_a[0] = 'f1f2_a'  # 修改列表元素
    f2()
    print 'f1_a={:s}'.format(f1_a[0])

>>> f1()
# 输出:
# f2_a=f2_a
# f1_a=f1_a
# f1_a=f1f2_a

方案2:使用函数属性

把f1_a作为f1函数的属性存储,这样在f2里可以直接访问并修改:

def f1():
    f1.f1_a = 'f1_a'  # 定义为函数属性
    def f2():
        f2_a = 'f2_a'
        print 'f2_a={:s}'.format(f2_a)
        print 'f1_a={:s}'.format(f1.f1_a)
        f1.f1_a = 'f1f2_a'  # 修改函数属性
    f2()
    print 'f1_a={:s}'.format(f1.f1_a)

>>> f1()
# 输出:
# f2_a=f2_a
# f1_a=f1_a
# f1_a=f1f2_a

这两个方案都能实现你修改嵌套作用域变量的需求,完美适配Python 2.7的环境。

内容的提问来源于stack exchange,提问作者Vladimir Zolotykh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:35:29