为什么:Python'导入x'然后重新'导入x为y'clobbers导入x?

时间:2014-02-04 16:53:19

标签: python nosetests python-unittest

所以,我有一个小的Python导入谜。我相信它应该是出于某种原因,因为Guido很少出错。但是,为什么会这样呢?

$ cat myModule.py
#!/usr/bin/python

class SomeModule(object):

    def __init__(self):
        print "in SomeModule.__init__ ! "

    def doSomething(self):
        print 'doing something.'

$ cat myTest.py
import unittest
from myModule import SomeModule

class TestMyModule(unittest.TestCase):

    def test_001(self):
        print "should see init below"
        sm = SomeModule()
        sm.doSomething()
        print "should see init above\n"

    def test_002(self):
        print "should not see init below."
        from myModule import SomeModule as SM2
        SM2.__init__ = lambda x: None
        sm2 = SM2()
        sm2.doSomething()
        print "should not have seen init above.\n"

    def test_bbb(self):
        print "Should see init below"
        sm = SomeModule()
        sm.doSomething()
        print "should see init above\n"

$ nosetests myTest.py -s
should see init below
in SomeModule.__init__ ! 
doing something.

should see init above
.should not see init below.
doing something.
should not have seen init above.

.Should see init below
doing something.
should see init above
.
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

最终测试不受中间测试导入的影响,对吧?我的直觉说我不必担心初始导入,因为第二次导入使用'as'。 因此,在上一次测试中,我希望看到初始化但我没有。

显然,第二个导入,'from myModule导入SomeModule为SM2',破坏了Some Module的初始导入,即使看起来它应该是一个完全独立的实体SM2,而不是SomeModule。

这对某人有意义吗?

1 个答案:

答案 0 :(得分:2)

此处的“问题”是SM2SomeModule同一类。在python中,每个模块只有一个“实例” - 重新导入将返回对同一对象的引用:

>>> import code
>>> import code as code2
>>> code is code2
True

在您的代码中,当您运行SM2.__init__ = lambda x: None时,您将替换该类的构造函数。这会影响SM2SomeModule以及可能从myModule 导入的任何其他代码。

如果您只是使用SM2= SomeModule将类别别名,那么同样的事情会发生。

这也是让新程序员在开始处理列表并期望分配给新变量来复制实际列表时感到惊讶的机制:

>>> a=[1]
>>> b=a
>>> b.append(2)
>>> print a
[1, 2]

您可以使用is在代码中验证对象的身份。请注意,这与 equality

不同
>>> []==[]
True
>>> [] is []
False