python namespace:__ main __.类不是package.Class的实例

Lar*_*nke 7 python namespaces

考虑你有两个如下定义的python文件.假设一个是通用包(class2),另一个执行特定覆盖并充当可执行文件(class1).

class1.py:

#!/usr/bin/python
class Test(object):
    pass

class Verificator():
    def check(self, myObject):
        if not isinstance( myObject, Test ):
            print "%s is no instance of %s" % (type(myObject),Test)
        else:
            print "OK!"

if __name__ == '__main__':
    from class2 import getTest

    v = Verificator()
    t = Test()
    v.check(t)
    s = getTest()
    v.check(s)
Run Code Online (Sandbox Code Playgroud)

class2.py:

from class1 import Test
def getTest():
    return Test()
Run Code Online (Sandbox Code Playgroud)

会发生的事情是第一次检查没问题,第二次检查失败.其原因是,t__main__.Test,而sclass1.Testv.check()支票__main__.Test,但在一天结束的时候它是同一类的吧?

有没有办法写v.check()这样的,它也接受class1.Test对象,或任何其他方式来解决这个问题?

use*_*342 7

如果您打算class1.py从其他地方导入,请将顶级代码移动if __name__ == '__main__': ...到一个单独的文件中.这样,主文件和class2同一个class1.Test类一起工作.

几乎做任何事都会打开一堆蠕虫.虽然您可以通过切换isinstance来解决直接问题type(myObject).__name__ == ...,但事实仍然是您的Python进程包含两个Test只应该有一个类的类.否则彼此无法区分的类别彼此无关,并且彼此失败了issubclass.这实际上保证了难以诊断的错误.

编辑
另一种选择是class1在执行main时显式导入类,如答案中所示.建议更进一步,确保类没有以double形式定义.例如,您可以将if __name__ == '__main__'块移动到文件的开头,并以以下结尾sys.exit(0):

if __name__ == '__main__':
    import class1, class2
    ... use only the public API with module prefixes ...
    sys.exit(0)

# the rest of the module follows here
Run Code Online (Sandbox Code Playgroud)


Ben*_*ott -2

您可以使用该type()函数(事实上,您会发现这种调用相当常见!):

#!/usr/bin/python
class Test(object):
    pass

class Verificator():
    def check(self, myObject):
        if not isinstance( type(myObject), type(Test) ):
            print "%s is no instance of %s" % (type(myObject),Test)
        else:
            print "OK!"

if __name__ == '__main__':
    from class2 import getTest

    v = Verificator()
    t = Test()
    v.check(t)
    s = getTest()
    v.check(s)
Run Code Online (Sandbox Code Playgroud)

也许更糟糕的解决方案:

if not isinstance( myObject.__class__, Test.__class__ ):  # Use __class__ here.
Run Code Online (Sandbox Code Playgroud)

它们当然是等价的,但除非您迫切需要,否则需要使用双下划线成员被认为是不好的形式!不过,了解它们的存在是值得的,因此我将其包含在我的答案中。

请注意,据我所知,这种情况会发生,因为当您运行时python class1.py,class1.py 将没有模块。因此,Python 会__main__为您将所有内容放入模块中。当您从任何其他脚本导入它时,情况并非如此,因此将某些内容视为__main__模块的一部分实际上是特殊情况!

  • 检查 isinstance(type(myObject), type(Test)) 仅测试 myObject 的类型是否由 Test 的元类创建。对于默认元类创建的任何两个新样式类来说都是如此,并且几乎可以肯定不是OP所要求的。 (5认同)