我的程序有问题,我能够在小规模上重现这种意外(至少对我来说是出乎意料的)行为,所以现在我确定这不是另一个错误。
假设我有 3 个 python 模块:one
、two
和 three
。
在three
我们有:
var = 0
list = []
所以我们有一个等于零和空列表的整数。
在two
我们有:
from three import var, list
def funct():
print var*2
print list
return
因此,我们导入var
和list
,并简单地定义一个将打印并返回的函数。
我没有在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 文档。
导入名称会将该名称包含的引用复制到模块中。在您的代码中,整数会反弹,但列表会发生变化。由于列表引用永远不会更改,因此原始对象会发生变化。因此不同的整数,相同的列表。