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