我观察到一个涉及对象“AuditResult”的奇怪现象,我希望有人可以帮助我理解。我有一个这样的模块设置:
model\ __init__.py common.py (AuditResult is imported from audit.py into here) audit.py (where AuditResult lives) objects.py test.py
在test.py中,如果我使用from common import AuditResult
导入AuditResult对象,则会出现以下结果:
>>> isinstance(audit_obj, AuditResult)
False
>>> type(audit_obj)
<class 'model.audit.AuditResult'>
>>> AuditResult
<class 'audit.AuditResult'>
但是,如果我使用from model.common import AuditResult
,代码将按预期运行。
>>> isinstance(audit_obj, AuditResult)
True
>>> type(audit_obj)
<class 'model.audit.AuditResult'>
>>> AuditResult
<class 'model.audit.AuditResult'>
答案 0 :(得分:5)
问题在于:
from common import AuditResult
将导入common
模块作为“独立模块”,同时:
from model.common import AuditResult
会将其导入为model
的子模块。 Python 在两个模块之间区分!在前一种方式导入的common
和在后一种情况下导入的common
之间存在无关系。由于代码执行两次AuditResult
是不同的类,因此isinstance
正确会在混合时返回False
。
你可以测试一下:
import common
from model import common as common2
print(common is common2)
你会看到这会打印False
。如果模块不同,所有内容都不同,所以:
print(common.AuditResult is common2.AuditResult)
将打印False
。
请记住,python 不对类型使用结构等价,即不检查“类是否基本相同”。 isinstance
只需检查与实例is
关联的类是否完全作为第二个参数传递。在您的情况下,两个 AuditResult
是不同的类,因此audit.AuditResult
的实例不是 {的实例{1}}。
事实上,这是我知道模块可以导入两次而不会弄乱导入机制内部的唯一方法。
我建议你避免绝对导入子模块,即:
model.audit.AuditResult
如果要进行相对导入,请使用相对导入语法:
from common import AuditResult
注意from .common import AuditResult
(点)。这告诉python从当前包中导入.
。