首页 > 解决方案 > 在 Python atexit 函数中,函数内设置的字符串不可见?

问题描述

我昨天在 Python 2.7.10 下遇到了(在我看来)一个不寻常的范围问题(尽管问题也在 Python 3 中)。我的 atexit 函数似乎看不到函数内设置的全局字符串,而全局列表很好。我已将问题案例简化为:

import atexit

myString1 = None
myString2 = None
myArray1 = []
myArray2 = []

def setString1(newString):
    myString1 = newString

def setArray1(newString):
    myArray1.append(newString)

def testFinishUp():
    print("myString1 = " + str(myString1))
    print("myString2 = " + str(myString2))
    print("myArray1  = " + str(myArray1))
    print("myArray2  = " + str(myArray2))

setString1("Hello")
myString2 = "World"
setArray1("HELLO")
myArray2.append("WORLD")
atexit.register(testFinishUp)

这个输出是:

myString1 = None
myString2 = World
myArray1  = ['HELLO']
myArray2  = ['WORLD']

现在,我确信 myString1 的行为方式与所有其他人的行为方式不同是有逻辑范围相关的原因,但我看不出它是什么。:-(

谁能解释一下这里发生了什么?谢谢!

标签: pythonpython-3.xpython-2.7scopeatexit

解决方案


这没什么好奇怪的。你的问题是这个陈述:

我的 atexit 函数似乎看不到函数内设置的全局字符串,而全局列表很好。

是假的。您没有在函数内设置全局字符串。相反,您在函数范围内创建它的本地版本,它会影响全局版本。如果你真的想改变全局值,你应该这样做:

def setString1(newString):
    global myString1
    myString1 = newString

它适用于您的列表的原因是您就地(通过append)修改它们而不是创建副本。如果你愿意

def setArray1(newString):
    myArray1 = myArray1 + [newString]

您会看到与字符串大小写完全相同的行为。

不过要提醒一句:从函数修改全局状态通常被认为是不好的风格,因为它混淆了值的设置位置。通常,最好在全局范围内修改值,例如通过分配给函数调用的结果。


推荐阅读