【问题标题】:In a Python atexit function, strings set inside a function aren't visible?在 Python atexit 函数中,函数内设置的字符串不可见?
【发布时间】:2020-04-02 08:56:31
【问题描述】:

昨天我在 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 的行为方式与所有其他人的行为方式不同是有逻辑范围相关的原因,但我看不出它是什么。 :-(

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

【问题讨论】:

  • 哦!这是你可以盯着看几个小时而不知道实际问题是什么的事情之一。谢谢大家非常有帮助的回复! :-)

标签: python python-3.x python-2.7 scope atexit


【解决方案1】:

这没什么好奇怪的。你的问题是这样的说法:

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

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

def setString1(newString):
    global myString1
    myString1 = newString

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

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

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

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

【讨论】:

    【解决方案2】:

    如果你想操作一个全局不可变变量,你需要在该函数中添加global var

    在您的情况下,您正在向数组添加一些内容,因此不会对数组引用进行操作,因此您无需指定这是一个全局变量,但字符串本身会被操作。

    添加:global myString1 上图:myString1 = newString

    应该能解决问题。

    更多阅读请参阅python doc

    【讨论】:

      猜你喜欢
      • 2018-09-30
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      • 2017-08-05
      • 2018-09-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多