Python "import" 作用域
我正在处理一些自动生成的Python代码。我想避免手动编辑这些Python文件,所以我有了这个问题:
foo.py:
def foo():
print "foo"
boo.py:
def boo():
foo.foo() # <-- global name 'foo' not defined
print "boo"
bar.py:
import foo
import boo
def bar():
boo.boo()
print "bar"
执行以下命令:
python.exe bar.py
会出现一个错误,提示boo
没有找到foo
。但是bar
是同时导入了foo
和boo
的。难道foo
不应该自动对boo
可用吗?
有没有办法解决这个问题?正如所说的,boo.py是自动生成的,我想避免在boo.py中添加import foo
。
谢谢。
5 个回答
每个模块都有自己的命名空间。也就是说,如果 boo.py 想要使用其他模块里的东西,它自己必须先导入这些东西。
其实可以设计一种语言,让命名空间像你想的那样堆叠,这种方式叫做动态作用域。有些语言,比如最早的 Lisp、早期版本的 Perl、PostScript 等,确实使用(或支持)动态作用域。
不过,大多数语言使用的是词法作用域。结果发现,这种方式让语言的工作变得更简单:这样一来,一个模块可以根据自己的代码来推测它是如何工作的,而不用担心它是怎么被调用的。
想了解更多细节,可以看看这篇文章:http://en.wikipedia.org/wiki/Scope_%28programming%29
不行。如果你想在 boo
中使用 foo
,你需要在 boo
中导入它。放在 bar
中的 import foo
只会让 foo
在 bar
模块中可用。
一般来说,Python 中的 import
语句有点像定义一个变量。你可以这样理解:在脑海中把
import boo
想象成
boo = __import__('boo')
(__import__
是 Python 解释器的一个内置函数,它要么导入一个模块,要么查找已经导入的模块的引用,并返回这个引用)
自动生成 boo.py
的东西做错了。它应该在那个文件的某个地方添加 import foo
。你可以在 bar.py
中这样做来解决这个问题:
import foo
import boo
boo.foo = foo
但其实你不应该这样做。(我同意 Alex Martelli 说的,这种做法实在是个大 hack)
但是 bar 里同时引入了 foo 和 boo。难道 foo 不应该自动对 boo 可用吗?
其实并不是这样的:import
就像其他绑定名字的方法一样,只是在一个特定的范围内有效,并不是“在你可能想要的所有范围内都有效”。
有没有办法可以做到这一点?正如所说,boo.py 是自动生成的,我想避免在 boo.py 中添加 import foo。
有一种非常糟糕的解决方法——我不想一直用这个(我宁愿把精力放在修复那个完全有问题的代码生成器上,因为如果它有这么大的错误,比如缺少一个重要的导入,那它还有其他什么可怕的错误呢?!),不过,嘿,这不是我的事...;-)
让 bar.py
开始...:
import foo
import boo
import __builtin__
__builtin__.foo = foo
这样你就把标识符 foo
变成了一个“假冒的、人工的内置名称”(这种名称在每个范围内都是可用的,除非被更近的范围中的其他绑定遮蔽)指向模块 foo
。
这不是 推荐的做法,只是一个临时的解决方法,用来应对生成 boo.py
的代码生成器中的明显错误。赶快修复这个错误,这样你就可以尽快摆脱这个临时解决方案!