【问题标题】:Issues with classes in module namespace模块命名空间中的类问题
【发布时间】:2016-01-31 17:54:14
【问题描述】:

我正在玩 python 的命名空间,我遇到了一些我无法解释的行为。特别是我想看看您是否可以使用“from module import *”之类的命令来停止导入类。在一个模块中,称之为moduleA,我有以下内容:

class __hi(object): pass

class hey(object):

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

然后在另一个模块中,比如 moduleB,我从 moduleA 导入“所有内容”

from moduleA import *

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

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

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

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

这个问题与所引用的完全不同。在链接的帖子中,名称与被损坏的变量所在的类变量相混淆。这不是我要问的。

编辑:

感谢 vaultah 指出:双下划线在该行中的位置无关紧要,它仍然会触发名称修改 - 但谁能解释为什么会这样?这意味着,在上述(高度人为的)情况下,您永远无法将一个类的实例保存在另一个类中。

【问题讨论】:

  • 你为什么不直接使用__all__?还是一个前导下划线?
  • 这不是我试图解决的技术问题 - 我只是不理解上述行为
  • 您似乎了解名称修改,所以让您感到惊讶的是什么?
  • 因为据我所知,变量 self.hey 根本不应该被命名。变量名根本没有下划线,只有存储在 self.hey 中的类实例的名称有下划线
  • @jonrsharpe - __all__thing 作为解决方案很酷。但我对名字 mangling 更好奇。

标签: python namespaces python-import name-mangling


【解决方案1】:

出现问题是因为双下划线在类中遇到时错位

您的课程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' ]

【讨论】:

    猜你喜欢
    • 2011-03-13
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多