shi*_*ino 85 python import module
假设我有一个名为的包bar
,它包含bar.py
:
a = None
def foobar():
print a
Run Code Online (Sandbox Code Playgroud)
并且__init__.py
:
from bar import a, foobar
Run Code Online (Sandbox Code Playgroud)
然后我执行这个脚本:
import bar
print bar.a
bar.a = 1
print bar.a
bar.foobar()
Run Code Online (Sandbox Code Playgroud)
这就是我的期望:
None
1
1
Run Code Online (Sandbox Code Playgroud)
这是我得到的:
None
1
None
Run Code Online (Sandbox Code Playgroud)
任何人都能解释我的错误观念吗?
aar*_*ing 82
你在用from bar import a
.a
成为导入模块的全局范围中的符号(或导入语句出现的任何范围).因此,当您为其分配新值时a
,您只需更改哪个值a
,而不是实际值.尝试导入bar.py
直接与import bar
中__init__.py
,并通过设置有进行实验bar.a = 1
.这样,您实际上正在修改bar.__dict__['a']
哪个是a
此上下文中的"真实"值.
它有三层融合,但bar.a = 1
改变了实际派生a
的模块中的值.它不会改变看到的值,因为它存在于实际文件中.您可以设置是否要更改它.bar
__init__.py
a
foobar
foobar
bar.py
bar.bar.a
这是使用语句from foo import bar
形式的危险之一import
:它分为bar
两个符号,一个从内部foo
开始全局可见,开始指向原始值,另一个符号在import
执行语句的范围内可见.更改符号指向的位置不会更改它指向的值.
当reload
从交互式解释器尝试模块时,这种东西是杀手.
Eri*_*got 20
这个问题困难的一个原因是,你有一个名为程序bar/bar.py
:import bar
可导入bar/__init__.py
或bar/bar.py
,取决于它完成,这使得它有点笨重跟踪哪些a
是bar.a
.
下面是它的工作原理:
理解发生的事情的关键是要意识到在你的__init__.py
,
from bar import a
Run Code Online (Sandbox Code Playgroud)
实际上做了类似的事情
a = bar.a # … with bar = bar/bar.py (as if bar were imported locally from __init__.py)
Run Code Online (Sandbox Code Playgroud)
并定义一个新变量(bar/__init__.py:a
如果你愿意的话).因此,您from bar import a
在__init__.py
绑定的名字bar/__init__.py:a
原来的bar.py:a
对象(None
).这就是为什么你可以做from bar import a as a2
的__init__.py
:在这种情况下,很显然,你有两个bar/bar.py:a
和一个不同的变量名bar/__init__.py:a2
(在你的情况下,这两个变量的名称只是碰巧都为a
,但他们仍然生活在不同的命名空间:在__init__.py
,他们是bar.a
和a
).
现在,当你这样做
import bar
print bar.a
Run Code Online (Sandbox Code Playgroud)
你正在访问变量bar/__init__.py:a
(因为import bar
导入你的bar/__init__.py
).这是您修改的变量(为1).你没有触及变量的内容bar/bar.py:a
.所以当你随后做的时候
bar.foobar()
Run Code Online (Sandbox Code Playgroud)
你叫bar/bar.py:foobar()
,它访问的变量a
从bar/bar.py
,这仍然是None
(时foobar()
被定义,它绑定变量名一劳永逸的,所以a
在bar.py
IS bar.py:a
,没有任何其他a
的另一模块定义的变量可能有许多a
在所有导入的模块变量).因此最后的None
输出.
Mar*_*tos 10
换句话说:结果证明这种误解很容易. 它在Python语言参考中被巧妙地定义:使用object而不是symbol.我建议Python语言参考使这更清晰,更少稀疏..
的
from
形式不结合模块名称:它通过标识符的列表,看起来它们中的每一个向上在步骤(1)中发现的模块中,并且在本地名称空间中的结合名称对象从而找到.
然而:
导入时,导入导入符号的当前值,并将其添加到定义的命名空间中. 您没有导入引用,您实际上是在导入值.
因此,要获取更新的值i
,必须导入一个包含对该符号的引用的变量.
换句话说,导入不像import
JAVA中的external
声明,C/C++中的声明甚use
至PERL中的子句.
相反,Python中的以下语句:
from some_other_module import a as x
Run Code Online (Sandbox Code Playgroud)
是更喜欢在K&R C以下代码:
extern int a; /* import from the EXTERN file */
int x = a;
Run Code Online (Sandbox Code Playgroud)
(警告:在Python的情况下,"a"和"x"本质上是对实际值的引用:你没有复制INT,你正在复制引用地址)
归档时间: |
|
查看次数: |
38474 次 |
最近记录: |