在模块中使用isinstance

时间:2014-02-01 12:44:19

标签: python

我观察到一个涉及对象“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'>

1 个答案:

答案 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从当前包中导入.