我应该如何在不污染其命名空间的情况下在Python模块中执行导入?
问题描述
我正在开发一个用于处理一些科学数据的Python包。我在包的任何模块中定义的几乎每个函数中都需要来自其他模块和包(包括NumPy)的多个常用类和函数。
如何用毕德学派的方法来处理这些问题?我考虑过多种变种,但每一种都有自己的缺点。
使用
from foreignmodule import Class1, Class2, function1, function2
导入模块级别的类
然后,可以从每个函数轻松访问导入的函数和类。另一方面,它们污染了模块命名空间,使dir(package.module)
和help(package.module)
与导入的函数杂乱无章使用
from foreignmodule import Class1, Class2, function1, function2
导入函数级类
函数和类易于访问,不会污染模块,但从每个函数中的多达十几个模块导入看起来像是大量重复代码。使用
import foreignmodule
在模块级别导入模块
由于需要在每个函数或类调用前添加模块名称,因此不会造成太多污染。使用一些人为的变通办法,如对所有这些操作使用函数体,并仅返回要导出的对象...像这样
def _export(): from foreignmodule import Class1, Class2, function1, function2 def myfunc(x): return function1(x, function2(x)) return myfunc myfunc = _export() del _export
这设法解决了模块命名空间污染和函数的易用性这两个问题...但它似乎一点也不像派德哲学。
解决方案
继续执行通常的from W import X, Y, Z
,然后使用__all__
特殊符号定义您希望用户从您的模块导入的实际符号:
__all__ = ('MyClass1', 'MyClass2', 'myvar1', …)
这定义了import *
从您的模块导入到用户模块中的符号。
一般来说,Python程序员应该而不是使用dir()
来确定如何使用您的模块,如果他们这样做了,则可能表明其他地方有问题。他们应该正在阅读您的文档或输入help(yourmodule)
以确定如何使用您的库。或者他们可以自己浏览源代码,在这种情况下,(A)您导入的东西和您定义的东西之间的区别非常明显,以及(B)他们将看到__all__
声明,并知道他们应该玩哪些玩具。
如果您试图在这种情况下支持dir()
而不是为它设计的任务,您将不得不对您自己的代码设置恼人的限制,我希望从这里的其他答案中可以清楚地看到这一点。我的建议是:别这么做!看看标准库的指导:只要代码清晰和简洁需要,它就会from … import …
,并提供(1)信息性文档字符串、(2)完整文档和(3)可读代码,因此任何人都不必在模块上运行dir()
并试图将导入与模块中实际定义的内容区分开来。
相关文章