Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
原因:Python';导入x';然后重新';将x导入为y';重击输入x?_Python_Nosetests_Python Unittest - Fatal编程技术网

原因:Python';导入x';然后重新';将x导入为y';重击输入x?

原因:Python';导入x';然后重新';将x导入为y';重击输入x?,python,nosetests,python-unittest,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.

所以,我有一个关于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,但我没有看到。

显然,第二个导入“from myModule import SomeModule as SM2”结束了某些模块的初始导入,尽管看起来它应该是一个完全独立的实体,如SM2,而不是SomeModule

这对某人有意义吗?

这里的“问题”是
SM2
SomeModule
同一类。在python中,每个模块只有一个“实例”——重新导入将返回对同一对象的引用:

>>> import code
>>> import code as code2
>>> code is code2
True
在您的代码中,当您运行
SM2.\uuuu init\uuuu=lambda x:None
时,您正在替换类的构造函数。这会影响
SM2
SomeModule
,以及可能从
myModule
导入的任何其他代码

如果您只是用
SM2=SomeModule
给类添加别名,也会发生同样的情况

当新程序员开始处理列表并期望分配给新变量以复制实际列表时,这也是让他们感到惊讶的相同机制:

>>> a=[1]
>>> b=a
>>> b.append(2)
>>> print a
[1, 2]
您可以使用
is
验证代码中对象的身份。注:这与平等不同:


这与导入无关
——它源于对Python如何处理导入的误解,这是来自其他语言的合理期望:我们认为它每次都会从文件系统读取,而不是从
sys.modules
(AFAIK没有很好的文档记录)。在进行挖掘之前,我们期望的更类似于一个
json.loads()
(本质上是一个深度副本),而不仅仅是将一个列表分配给第二个variable@Izkata你是对的,我没有考虑到<代码>导入< /代码>的行为对于一个新的Python用户可能并不明显。我编辑了这个问题来解释这一点
>>> []==[]
True
>>> [] is []
False