【问题标题】:Python: Local variables mysteriously update Global variablesPython:局部变量神秘地更新全局变量
【发布时间】:2012-12-26 21:23:42
【问题描述】:

我有一个函数,我在其中使用局部变量,然后在函数完成后传回最终变量。我想记录这个变量在函数之前是什么,但是全局变量与局部变量一起更新。这是我的代码的缩写版本(很长)

def Turn(P,Llocal,T,oflag):
    #The function here changes P, Llocal and T then passes those values back
    return(P, Llocal, T, oflag)

#Later I call the function
#P and L are defined here, then I copy them to other variables to save
#the initial values

P=Pinitial
L=Linitial
P,L,T,oflag = Turn(P,L,T,oflag)

我的问题是 L 和 Linitial 都在 Llocal 更新时准确更新,但我希望 Linitial 不改变。 P 没有改变,所以我对这里发生的事情感到困惑。帮助?谢谢!

勇敢者的完整代码在这里:https://docs.google.com/document/d/1e6VJnZgVqlYGgYb6X0cCIF-7-npShM7RXL9nXd_pT-o/edit

【问题讨论】:

  • 对象有哪些类型?你能给出一个完整的、独立的可运行示例来展示你所看到的吗?
  • P 是一个整数,L 是一个列表。 T 也是一个 int,oflag 是一个 bool。我只是通过 IDLE 的调试器发现了这个问题,它非常微妙。但是,如果我显示全局变量和局部变量,我会看到 L、Linitial 和 Llocal 这三个变量同时发生变化。我可以在这里上传整个代码,但它有几百行。我现在担心的部分从 190 和 57 开始。目前它从第 66 行抛出错误,但错误的根本原因是这个变量更新。
  • 请注意PEP-8 建议为类名保留CapWords
  • @user1930726 制作一个简短(但可运行)的示例来说明问题。
  • 下次使用pastebin.com 或类似的工具来分享您的代码。 :)

标签: python variables global local


【解决方案1】:

问题是 P 和 L 是 namesboundobjects,而不是值本身。当您将它们作为参数传递给函数时,实际上是将绑定的副本传递给 P 和 L。这意味着,如果 P 和 L 是可变对象,则对它们所做的任何更改都将在函数调用之外可见.

您可以使用copy 模块来保存名称值的副本。

【讨论】:

  • 请注意,copy 是一个模块,而不是一个函数。
  • 我认为在这种情况下,理解函数接收指针并在与初始对象相同的对象上操作就足够了。但是,不可变对象通常在赋值时隐式复制(例如数字和字符串),而可变对象将相同的指针分配给新名称,因此您有两个名称引用同一个实例。
  • @Nisan.H Python 语言没有“指针”的概念,所以这没有用(尽管 cPython 的实现确实使用了指针)。并且不可变对象不会“在分配时复制”。该名称只是重新绑定到分配给的任何内容。
【解决方案2】:

列表是可变的。如果您将列表传递给函数并且该函数修改了列表,那么您将能够看到绑定到同一列表的任何其他名称的修改。

要解决此问题,请尝试更改此行:

L = Linitial

到这里:

L = Linitial[:]

此切片制作列表的浅表副本。如果您从存储在L 的列表中添加或删除项目,它不会更改列表Lintial

如果要进行深层复制,请使用copy.deepcopy


P 不会发生同样的事情,因为它是一个整数。整数是不可变的。

【讨论】:

  • 我尝试过使用 copy.deepcopy 和 L = Linitial[:] 但我仍然遇到与以前相同的错误。我正在使用调试器解决它,当我看到发生了什么时我会发回。谢谢!
  • 现在可以使用了!实际上,当我定义 Linitial 和重新定义 L 时,我不得不制作两次浅拷贝。谢谢!!
【解决方案3】:

在 Python 中,变量只是对内存中对象或值的引用。例如,当您有一个列表x

x = [1, 2, 3]

因此,当您将x 分配给另一个变量时,我们称之为y,您只是在为x[1, 2, 3] 列表)引用的对象创建一个新引用(y)。

y = x

当你更新x时,你实际上是在更新x指向的对象,即列表[1, 2, 3]。由于y 引用了相同的值,它似乎也被更新了。

请记住,变量只是对对象的引用。

如果你真的想复制一个列表,你应该这样做:

new_list = old_list[:]

这里有一个很好的解释:http://henry.precheur.org/python/copy_list

【讨论】:

    猜你喜欢
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2018-10-26
    • 1970-01-01
    • 2022-11-14
    相关资源
    最近更新 更多