模块命名空间中的类的问题

时间:2016-01-31 17:54:15

标签: python namespaces python-import name-mangling

我正在玩python的命名空间,我遇到了一些我无法解释的行为。特别是我想知道你是否可以使用像'from module import *'这样的命令来停止导入类。在一个模块中,将其命名为moduleA,我有以下内容:

class __hi(object): pass

class hey(object):

    def __init__(self):
        # self.hey = __hi()

然后在另一个模块中,比如moduleB,我使用

从moduleA导入'everything'
from moduleA import *

这具有导入类'hey'但类__hi的预期效果。

现在当取消注释'#self.hey = __hi()'上面的行时,我得到一个我不明白的错误:

"NameError: global name '_hey__hi' is not defined"

看起来python已经破坏了变量名,因为类名有一个双下划线。谁能解释一下呢?

这个问题与引用的问题完全不同。在链接的帖子中,名称被修改了变量所在的类变量。这不是我要问的。

编辑:

感谢vaultah指出:无论双线下划线在哪里,它仍然会触发名称错位 - 但有人可以解释为什么会这样吗?这意味着,在如上所述的(高度设计的)情境中,你永远不能在另一个类中保存一个类的实例。

1 个答案:

答案 0 :(得分:0)

出现此问题的原因是,当在类中遇到双下划线时,它们会被损坏

您的班级hey包含行self.hey = __hi(),因为它位于一个类中,__hi被绑定到_hey__hi,但失败了

您可以通过将__hi替换为单下划线_hi,或删除下划线或任何其他方式来解决此问题。你可以在一个块中声明你的助手类,该块在文件完成解析之前退出并销毁名称:

def create_hey():
    class __hi:
        pass

    x = __hi

    class hey:
        def __init__():
            self.__hi = x()

    return hey

hey = create_hey()

但实际上,这需要做很多工作。很多评论者建议你做得更好,只需定义__all__以控制可导入的内容:

__all__ = [ 'hey' ]