意外的导入行为,以不同的方式处理整数和列表



我的程序有问题,我能够在小规模上重现这种意外(至少对我来说是出乎意料的)行为,所以现在我确定这不是另一个错误。

假设我有 3 个 python 模块:onetwothree

three我们有:

var = 0
list = []

所以我们有一个等于零和空列表的整数。

two我们有:

from three import var, list
def funct():
    print var*2
    print list
    return

因此,我们导入varlist,并简单地定义一个将打印并返回的函数。

我没有在two中调用funct(),而是在one中调用它,但不是在对它们进行一些"操作"之前。

from three import var, list
from two import funct
if 2 < 4:
    var += 1
    list.append("x")
print funct()

所以我的问题来了。

我万万没想到会有这样的结果:

0
['x']
None

为什么x被添加到列表中,append()而 1 没有添加到 var 中,需要清楚。我期待:

2
['x']
None

如果发现很奇怪,他们在相同的情况下接受不同的治疗。

  • 我在这里错过了什么吗?
  • 我在进口方面做错了什么吗?

如果没有:

  • 为什么它的行为是这样的?
  • 应该如何解决/处理这个问题?

提前谢谢。

要"修复"你的程序,你必须添加"global var",如下所示:

if 2 < 4:
     global var
     var += 1
     list.append("x")

但根据 http://docs.python.org/reference/simple_stmts.html#global 的说法,这是非法的:

全局语句中列出的名称不得定义为形式参数,也不得定义为 for 循环控制目标、类定义、函数定义或导入语句中。

然后,按照上面的链接:

CPython 实现细节:当前的实现不强制后两个限制,但程序不应滥用这种自由,因为未来的实现可能会强制执行它们或默默地改变程序的含义。

编辑:

解决方案是更改:

from three import var, list

自:

from three import list
import three

然后不要使用全局命名空间,而是显式指定三个命名空间(您导入了符号)

法典:

three.var += 1

确保在其导入/从语句中相应地更改 two.py 和 one.py

http://docs.python.org/tutorial/modules.html#more-on-modules

每个模块都有自己的私有符号表,该表由

模块中定义的所有函数用作全局符号表。因此,模块的作者可以在模块中使用全局变量,而不必担心与用户的全局变量发生意外冲突。另一方面,如果你知道自己在做什么,你可以用与引用其函数modname.itemname相同的符号触摸模块的全局变量。

这与导入无关,而与所涉及的不同类型有关。

list是可变类型。 list.append修改对象,并返回None

int是不可变的类型。它的+=运算符返回一个新对象。

有关可变和不可变类型的更多信息,请参阅其数据模型的 Python 文档。

导入名称会将该名称包含的引用复制到模块中。在您的代码中,整数会反弹,但列表会发生变化。由于列表引用永远不会更改,因此原始对象会发生变化。因此不同的整数,相同的列表。

相关内容

  • 没有找到相关文章

最新更新