7

假设您有两个如下定义的 python 文件。假设一个是通用包(class2),另一个是特定的覆盖并用作可执行文件(class1)。

类1.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)

类2.py:

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

发生的情况是第一次检查正常,而第二次检查失败。原因是twhile __main__.Testissclass1.Test检查v.check()__main__.Test但归根结底它是同一类,对吗?

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

4

3 回答 3

7

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

做几乎任何其他事情都会打开一罐蠕虫。isinstance虽然您可以通过切换到 来解决眼前的问题type(myObject).__name__ == ...,但事实仍然是您的 Python 进程包含两个Test类,而这些类应该只有一个。否则无法区分的类彼此一无所知,并且无法通过彼此的issubclass测试。这实际上保证了难以诊断的错误。

编辑
另一个选择是在class1作为主要执行时显式导入类,如您的答案中所示。建议更进一步,确保类不是以双精度定义的。例如,您可以将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
于 2013-03-01T14:49:14.677 回答
1

感谢您的提示,这最终帮助我朝着正确的方向进行实验。我刚刚在这个玩具模型中找到的解决方案是使用导入来修复命名空间问题。为了排除 user4815162342 指出的问题,我在 class1 中添加了另一个类。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)
于 2013-03-01T16:57:42.410 回答
-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)

可能更糟糕的解决方案:

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

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

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

于 2013-03-01T14:31:28.667 回答