【问题标题】:Why: Python 'Import x' then Re- 'import x as y' clobbers import of x?为什么:Python 'Import x' 然后 Re- 'import x as y' 破坏 x 的导入?
【发布时间】:2014-02-04 16:53:19
【问题描述】:

所以,我有一个小的 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”。 因此,在最后一次测试中,我希望看到 init 但我没有。

显然,第二次导入,“从 myModule 导入 SomeModule 作为 SM2”,破坏了 Some Module 的初始导入,尽管它看起来应该是一个完全独立的实体,如 SM2,而不是 SomeModule。

这对某人有意义吗?

【问题讨论】:

    标签: python nosetests python-unittest


    【解决方案1】:

    这里的“问题”是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 验证代码中对象的身份。请注意,这与 平等 不同:

    >>> []==[]
    True
    >>> [] is []
    False
    

    【讨论】:

    • this has nothing whatsoever to do with imports - 它来自对 Python 如何处理导入的误解,来自其他语言的合理期望:我们认为它每次都会从文件系统中读取,而不是从 @ 中提取987654333@(AFAIK 没有很好的记录)。在进行挖掘之前,我们期望的更像是json.loads()(本质上是一个深拷贝),而不是仅仅将一个列表分配给第二个变量
    • @Izkata 你说得对,我没有考虑到import 的行为对于新的python 用户可能并不明显。我已经编辑了问题来解释这一点
    猜你喜欢
    • 2015-07-31
    • 2015-10-01
    • 2017-09-18
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多