在主Python模块中调用isinstance

时间:2014-03-11 10:14:39

标签: python

如果在__main__空间中使用,则存在异常的异常行为。

考虑以下代码

a.py:

class A(object):
    pass

if __name__ == "__main__":
    from b import B
    b = B()
    print(isinstance(b, A))

b.py

from a import A
class B(A):
    pass

main.py

from a import A
from b import B

b = B()
print(isinstance(b, A))

当我运行main.py时,我按预期得到True,但当我运行a.py时,我得到False。看起来A的名称在那里获得前缀__main__

如何获得一致的行为? 我需要在B中导入a.py以在doctest文件上运行a.py

2 个答案:

答案 0 :(得分:6)

WSo运行a.py时会发生什么是Python读取a.py并执行它。在执行此操作时,它会导入模块b,它导入模块a,但它不会重复使用先前解析它的定义。现在,您在a.py中有两个定义副本,分别称为模块__main__a,因此不同__main__.Aa.A

通常,您应该避免导入正在执行的模块。相反,您可以创建一个新文件来运行doctests并使用类似

的内容
import a
import doctest

doctest.testmod(a)

并从模块__main__中移除a部分。

答案 1 :(得分:1)

事件链:

  1. 调用a.py脚本。
  2. 执行class A语句,在A中创建__main__ 命名空间。
  3. b已导入。
  4. 在b.py a导入。
  5. 执行class A语句,在A命名空间中创建aA命名空间中的aA中的__main__无关 b.py命名空间,而不是由它生成的 码。它们是不同的对象。

  6. 我同意赫尔穆特的观点,即最好避免这种循环进口。但是,如果您希望使用最少的更改来修复代码,则可以执行以下操作:

    让我们重命名bmodule.py - > b所以我们可以将b模块与class A(object): pass if __name__ == "__main__": import bmodule b = bmodule.B() print(isinstance(b, bmodule.A)) 变量区分开来(希望在您的真实代码中这些名称已经是不同的):

    True
    

    打印

    {{1}}