Python中意外的相对导入行为
今天我遇到了一个非常令人吃惊的相对进口行为(在将头发拉出近4个小时后不幸地)。
我一直认为,如果您在名为“包”的包中的模块名称“module_a.py”内有“A类”,您可以等效地使用:
from package.module_a import ClassA
要么
from module_a import ClassA
只要您从“包装”内的模块导入。 我明白这是相对重要的。
直到今天,我还没有遇到过问题,因为我需要检查对象A的实例,并且我很惊讶地发现一个非常不寻常的行为。
考虑以下:
包/ module_a.py
class ClassA(object):
pass
def check_from_module_a(obj):
print 'from module_a'
print '-------------'
print 'class is:', ClassA
print 'object is', type(obj)
print 'is obj a ClassA:', isinstance(obj, ClassA)
包/ module_b.py
from package.module_a import ClassA
from module_a import check_from_module_a
a = ClassA()
check_from_module_a(a)
print ' '
print 'from module_b'
print '-------------'
print 'class is:', ClassA
print 'object is', type(a)
print 'is obj a ClassA:', isinstance(a, ClassA)
现在执行module_b.py时你会得到:
from module_a
-------------
class is: <class 'module_a.ClassA'>
object is <class 'package.module_a.ClassA'>
is obj a ClassA: False
from module_b
-------------
class is: <class 'package.module_a.ClassA'>
object is <class 'package.module_a.ClassA'>
is obj a ClassA: True
我遵循逻辑,现在看看为什么会出现这种情况 - 这并不明显,因为我认为无论是绝对导入还是相对导入,ClassA的绑定都是相同的。 这给我造成了一个非常难以分离的bug。
我的问题:
这是预期的行为吗?
如果这是它应该工作的逻辑方式 - 那么我不清楚为什么我会使用相对进口,如果它们与绝对进口不相容(在上述意义上)。 这里有一个很好的解释,我失踪了吗?
我始终认为,当子包装结构可能会移动时,相对导入可以为大型重构提供更多的便利。 这是相对导入的主要好处吗?
由于隐含的相对导入导致了问题,因此它们在Python 3中已被删除。您经常不会对它们产生预期的行为。 参见PEP-328进行讨论。 如果您使用与基本(库存)模块相同的名称定义子包名称,则尤其如此。
(1)是的,这是预期的行为。
(2)显式相对导入是
from .module_a import ClassA
, 并不是
from module_a import ClassA
它可以是相对的也可以是绝对的,并且可以在顶层包和模块之间产生冲突。
(3)是的,这是相对重要的优势之一。 主要好处是可能不得不输入:)
链接地址: http://www.djcxy.com/p/52473.html上一篇: Unexpected relative import behavior in Python
下一篇: JSP Progress Bar