美文网首页python
python import 和from import 区别

python import 和from import 区别

作者: 茫子 | 来源:发表于2017-12-26 18:32 被阅读0次

python import 和from import 区别,以及在mock中的应用

前言

写python肯定会使用很多import 或者是from xxx import AAA
两者到底有什么区别呢?

关键原理

主要是 全局命名空间 的区别,全局命名空间可以用 globals() 函数查看。
全局命名空间虽然叫做全局,但是实际只是模块(一个模块,即是一个python文件)级别的命名空间。

区别表现

  1. 使用import xxx 到导入的是模块,导入后使用globals()看到xxx模块信息
  2. 使用from xxx import AAA导入的是对象(函数,类,变量),导入后使用globals()看到AAA信息

比如文件CCC.py:

import AAA
from BBB import funcB
print globals()
funcB()

就会有如下输出:

{
  'AAA': < module 'AAA' from 'AAA.pyc' > ,
  'funcB': < function funcB at 0x1d9b668 > ,
}

有什么意义?

其实这个时候,funcB,已经是模块CCC里的funcB了. 换句话说,在CCC文件的最后一行调用的funcB,实际是从CCC的全局命名空间里面找到了funcB这个函数。
更深层的说:如果这个时候对 BBB.funcB做出修改或扩展是不能够影响到CCC.funcB的,比如在使用Mock的时候。

常见场景

最常见的情况就是做单元测试的时候。
有文件CCC.py

import AAA
from BBB import funcB

def useFuncB():
    return funcB()
def useFuncA():
    return AAA.funcA()

现在需要对CCC里面的useFuncB和useFuncA做单元测试,但是AAA和BBB都还没有准备好,mock应该需要出现了

import CCC

class TestCCC(unittest.TestCase):
"""测试CCC"""

def test_userFuncB(self):
    """测试FuncB"""
    with mock.patch("BBB.funcB") as mockobj:
            mockobj.return_value =  "your expect"
            self.assertTrue(CCC.useFuncB() == "your expect")

def test_userFuncA(self):
    """测试FuncA"""
    with mock.patch("AAA.funcA") as mockobj:
            mockobj.return_value =  "your expect"
            self.assertTrue(CCC.useFuncA() == "your expect")

在如上代码中

  1. test_userFuncB 总是不能得到如期结果
  2. test_userFuncA 可以得到如期结果
    原因就是: mock对象确实是修改BBB.funcB,但是CCC.useFuncB根本没有使用BBB.funcB,而是使用了CCC.funcB。

怎么办?

减少使用from xxx import BBB,特别是from xxx import * 这样的使用模式。后者将会污染全局命名空间

PS

上文的例子主要是为了介绍原理,并没有完整运行过。

相关文章

网友评论

    本文标题:python import 和from import 区别

    本文链接:https://www.haomeiwen.com/subject/ooojgxtx.html