对于通过包和直接从同一模块导入的类型,isinstance失败

发布于 2021-01-29 15:59:40

/Project
|-- main.py
|--/lib
|  |--__init__.py
|  |--foo.py
|  |--Types.py

/Project/lib已添加到PYTHONPATH变量中。

Types.py:

class Custom(object):
    def __init__(self):
        a = 1
        b = 2

foo.py:

from Types import Custom
def foo(o):
    assert isinstance(o, Custom)

最后,来自 main.py

from lib.Types import Custom
from lib.foo import foo
a = Custom()
foo(a)

现在的问题是,它a的类型为lib.foo.Custom,而isinstance调用将检查其是否等于foo.Custom,这显然返回false。

如何避免此问题,而不必更改库(lib)中的任何内容?

关注者
0
被浏览
47
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您不应该同时制作lib一个程序包并将其添加到中PYTHONPATH。这样就可以lib.直接或直接导入其模块,从而为失败做好准备。

    如你看到的,

    lib.Types.Custom != Types.Custom
    

    因为Python导入的工作方式

    Python搜索导入路径并解析其找到的适当条目。

    • 导入时lib.Types,它将lib目录导入为一个包,然后导入lib/Types.py为其中的子模块,liblib.Types在中创建模块对象sys.modules
    • 当您导入Types,它导入Types.py作为一个独立的模块,创建模块对象Typessys.modules

    所以,Typeslib.Types最终成为两个不同的模块对象。Python不会检查它们是否是同一文件,以使事情变得简单并避免再次猜测。

    (这实际上在Python的Import System中的Unwary陷阱中列为“双重导入陷阱”。)


    如果lib从中删除PYTHONPATH,则导入lib/foo.py将需要成为相对导入:

    from .Types import Custom
    

    或绝对导入:

    from lib.Types import Custom
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看