Python "import" 作用域

13 投票
5 回答
24080 浏览
提问于 2025-04-16 00:21

我正在处理一些自动生成的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是同时导入了fooboo的。难道foo不应该自动对boo可用吗?

有没有办法解决这个问题?正如所说的,boo.py是自动生成的,我想避免在boo.py中添加import foo

谢谢。

5 个回答

4

每个模块都有自己的命名空间。也就是说,如果 boo.py 想要使用其他模块里的东西,它自己必须先导入这些东西。

其实可以设计一种语言,让命名空间像你想的那样堆叠,这种方式叫做动态作用域。有些语言,比如最早的 Lisp、早期版本的 Perl、PostScript 等,确实使用(或支持)动态作用域。

不过,大多数语言使用的是词法作用域。结果发现,这种方式让语言的工作变得更简单:这样一来,一个模块可以根据自己的代码来推测它是如何工作的,而不用担心它是怎么被调用的。

想了解更多细节,可以看看这篇文章:http://en.wikipedia.org/wiki/Scope_%28programming%29

7

不行。如果你想在 boo 中使用 foo,你需要在 boo 中导入它。放在 bar 中的 import foo 只会让 foobar 模块中可用。

一般来说,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)

19

但是 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 的代码生成器中的明显错误。赶快修复这个错误,这样你就可以尽快摆脱这个临时解决方案!

撰写回答