简体   繁体   English

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

[英]python namespace: __main__.Class not isinstance of package.Class

Consider you have two python files as defined below. 考虑你有两个如下定义的python文件。 Say one is a general package ( class2 ), and the other one does specific overrides and serves as the executable ( class1 ). 假设一个是通用包( class2 ),另一个包含特定的覆盖并用作可执行文件( class1 )。

class1.py: 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)

class2.py: class2.py:

from class1 import Test
def getTest():
    return Test()

What happens is that the first check is OK, where the second fails. 会发生的事情是第一次检查没问题,第二次检查失败。 The reason is that t is __main__.Test whereas s is class1.Test and v.check() checks for __main__.Test , but at the end of the day it is the same class, right? 原因是t__main__.Testsclass1.Testv.check()检查__main__.Test ,但是在一天结束时它是同一个类,对吧?

Is there a way to write v.check() such that it also accepts class1.Test objects, or any other way to solve this? 有没有办法写v.check() ,以便它也接受class1.Test对象,或任何其他方式来解决这个问题?

If you plan to import class1.py from elsewhere, move the top-level code ( if __name__ == '__main__': ... to a separate file altogether. That way both the main file and class2 work with the same class1.Test class. 如果您打算从其他地方导入class1.py ,请将顶级代码( if __name__ == '__main__': ...到一个单独的文件中。这样主文件和class2可以使用相同的class1.Test类。

Doing almost anything else opens a can of worms. 几乎做任何事都会打开一堆蠕虫。 While you can work around the immediate problem by switching isinstance to type(myObject).__name__ == ... , the fact remains that your Python process contains two Test classes where there should be only one. 虽然你可以通过将isinstance切换到type(myObject).__name__ == ...来解决当前问题,但事实仍然是你的Python进程包含两个Test类,其中只有一个。 The otherwise indistinguishable classes know nothing of each other and fail each other's issubclass tests. 其他无法区分的类彼此无关,并且彼此失败的issubclass测试。 This practically guarantees hard-to-diagnose bugs further down the line. 这实际上保证了难以诊断的错误。

EDIT 编辑
Another option is to explicitly import the classes from class1 when executing as main, as in your answer. 另一种选择是在执行main时从class1显式导入类,如答案中所示。 It would be advisable to go one step further and make sure that the classes aren't defined in double. 建议更进一步,确保类没有以double形式定义。 For example, you can move the if __name__ == '__main__' block to the beginning of the file, and end it with sys.exit(0) : 例如,您可以将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

Thanks for the hints, which finally helped me to experiment in the right direction. 感谢提示,最终帮助我尝试了正确的方向。 The solution I just found in this toy model, is to fix the namespace issue using an import. 我刚在这个玩具模型中找到的解决方案是使用导入修复命名空间问题。 In order to rule out the issue user4815162342 pointed out, I added another class to class1. 为了排除user4815162342指出的问题,我在class1中添加了另一个类。 The following code for class1.py appears to do, what I want: class1.py的以下代码似乎可以做,我想要的:

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

class Toast(object):
    pass

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

if __name__ == '__main__':
    from class2 import getTest
    from class1 import Test, Toast

    v = Verificator()
    t = Test()
    v.check(t)
    t = getTest()
    v.check(t)
    t = Toast()
    v.check(t)

You could use the type() function (you'll find this invocation fairly common, in fact!): 你可以使用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)

The perhaps worse solution: 可能更糟的解决方案:

if not isinstance( myObject.__class__, Test.__class__ ):  # Use __class__ here.

They're of course equivalent, but it's considered bad form to need to use double-underscore members unless you desperately need to! 它们当然是等价的,但除非你迫切需要使用双下划线成员,否则它被认为是不好的形式! It's worth knowing of their existence, though, hence why I've included this one in my answer. 但是,值得知道它们的存在,因此我将这个包含在我的答案中。

Note that this happens, to the best of my knowledge, because when you run python class1.py , class1.py would have no module. 请注意,据我所知,这种情况会发生,因为当您运行python class1.py ,class1.py将没有模块。 As such, python places everything into the __main__ module for you. 因此,python将所有内容放入__main__模块中。 This isn't the case when you import it from any other script, so seeing something as part of the __main__ module is actually the special case! 当您从任何其他脚本导入它时,情况并非如此,因此将某些内容视为__main__模块的一部分实际上就是特殊情况!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM