Python命名空间在内置与全局之间?

2 投票
3 回答
1316 浏览
提问于 2025-04-15 23:46

根据我的理解,Python 有以下几种最外层的命名空间:

内置命名空间 - 这个命名空间在整个解释器中都是全局的,所有在这个解释器实例中运行的脚本都可以访问。

全局命名空间 - 这个命名空间在一个模块内是全局的,也就是说在一个文件中。

我在寻找一个介于这两者之间的命名空间,想要在主脚本中共享一些变量给被调用的模块。

比如,script.py 文件:

import Log from Log
import foo from foo

log = Log()
foo()

还有 foo.py 文件:

def foo():
    log.Log('test')  # I want this to refer to the callers log object

我希望能够多次调用 script.py,并且在每次调用时,将模块级别的 log 对象暴露给 foo 方法。

有没有人知道这样做是否可能?

虽然传递 log 对象并不会太麻烦,但我正在处理一大段从 Javascript 移植过来的代码。我也明白这会对调用 foo 的部分造成一些限制,要求它必须暴露自己的 log 对象。

谢谢,

保罗

3 个回答

0

其实,我找到了我想要的东西。

这个技巧实际上是用到了 PLY,而我就是在这里发现的。

这个库的代码可能会在运行时出现错误,这样就可以访问调用者的堆栈信息。

0

没有这样的范围。你需要要么把它添加到内置的范围里,要么把相关的对象传递过去。

4

在内置模块和全局模块之间并没有一个“命名空间”,不过你可以很简单地创建自己的命名空间,并把它们用名字放进 sys.modules 里,这样其他模块就可以“导入”它们了(最好不要用 from ... import 这种写法,因为它会带来很多问题,当然也不要用你自己发明的 import ... from 这种写法,这样会直接报语法错误)。比如,在 script.py 里:

import sys
import types
sys.modules['yay'] = types.ModuleType('yay')

import Log
import foo

yay.log = Log.Log()
foo.foo()

foo.py 里:

import yay

def foo():
  yay.log.Log('test')

不要害怕带有前缀的名字——它们是好东西!就像《Python之禅》的最后一句话(也就是 import this)所说的:

Namespaces are one honking great idea -- let's do more of those!

你可以更简单地创建和使用“更多这样的东西”——只需给你的名字加上前缀(把它们放在合适的命名空间里)而不是坚持使用不合适的简单名字。使用带前缀的名字可以让很多事情变得简单,而对于那些固执于简单名字的人来说,很多事情可能会变得非常麻烦,甚至几乎无法实现!-)

撰写回答