我希望某个模块的接口包含一定数量的函数和类(没有别的)。我可以在一个文件中实现所有这些,并且可以轻松获得我想要的界面。但是,由于存在大量代码,我更愿意将整个内容分成几个文件
mypackage/
__init__.py
a.py
b.py
c.py
d.py
无论如何要获得所需的界面,我定义了一个 __init__.py
从中导入所有公共符号的包的文件 a
, b
, c
和 d
:
from a import func_a1, func_a2, ClassA1, ClassA2
from b import func_b1, func_b2, ClassB1, ClassB2
from c import func_c1, func_c2, ClassC1, ClassC2
from d import func_d1, func_d2, ClassD1, ClassD2
如果我使用导入包
import mypackage
包命名空间还包含符号 a
, b
, c
和 d
。这些名称是实现细节,而不是我的界面的一部分。我不希望它们显示为“公共”符号。摆脱它们的最佳方法是什么?
我考虑的选项是
使用单个模块而不是包。界面看起来很好,但实现将不如现在清晰。
添加行
del a, b, c, d
到了最后 __init__.py
。工作正常,但似乎是一个黑客。 (例如,你不能 import __init__
更多,没有这条线就可以工作。)
改名 a
, b
, c
和 d
至 _a
, _b
, _c
和 _d
。现在他们被包括在内 mypackage
作为“私人”符号的命名空间,我很好,但感觉有点奇怪 所有 我的文件名以下划线开头(实际上,当然有四个以上的子模块)。
还有更好的建议?或者想要选择哪个选项?
或者我只是肛门,不应该关心整个事情?
如果你真的想从命名空间中删除名称,那么你可以使用 del
对他们的陈述,他们会像风一样消失。
如果包中的某些文件确实是实现细节,请继续在它们前面加上下划线 - 这就是我们使用它们的原因。
例如,如果你查看 ctypes
你会看到的
__init__.py
==================================================
"""create and manipulate C data types in Python"""
import os as _os, sys as _sys
__version__ = "1.1.0"
from _ctypes import Union, Structure, Array
from _ctypes import _Pointer
from _ctypes import CFuncPtr as _CFuncPtr
...
正如你所看到的,甚至 os
和 sys
成为该文件中的实现细节。
这是一个受Javascript单功能模块启发的解决方案:
def __init__module():
from os import path
def _module_export_1():
return path.abspath('../foo')
def _module_export_2():
return path.relpath('foo/bar', 'foo')
g = globals()
g['module_export_1'] = _module_export_1
g['module_export_2'] = _module_export_2
__init__module()
虽然模块需要从os导入'path',但'path'不会污染模块名称空间。模块命名空间中唯一的缺点是__init_module(),它通过双下划线前缀明确标记为私有。
另一种选择是在每个函数的顶部导入所需的模块,而不是模块的顶部。第一次导入模块后,后续导入只是sys.modules字典中的查找。
但我同意这里的其他评论者 - Python约定不要担心模块命名空间污染,只是让模块的用户明白命名空间的哪些部分是你的公共API,哪些是内部的。
从 http://docs.python.org/tutorial/modules.html:
import语句使用
遵循惯例:如果一个包
__init__.py代码定义了一个名为__all__的列表,它被视为应该导入的模块名称列表
当从包导入*是
遇到。
在你的 mypackage/__init__.py
,尝试添加这个:
# add this line, replace "..." with the rest of the definitions
# you want made public
__all__ = ['func_a1', 'func_a2', 'ClassA1', 'ClassA2', ...]
from a import func_a1, func_a2, ClassA1, ClassA2
from b import func_b1, func_b2, ClassB1, ClassB2
from c import func_c1, func_c2, ClassC1, ClassC2
from d import func_d1, func_d2, ClassD1, ClassD2