从 __init__ 中的 Python 子模块导入方法,但不是子模块本身
Import method from Python submodule in __init__, but not submodule itself
我有一个具有以下结构的 Python 模块:
mymod/
__init__.py
tools.py
# __init__.py
from .tools import foo
# tools.py
def foo():
return 42
现在,当 import mymod
时,我看到它有以下成员:
mymod.foo()
mymod.tools.foo()
不过我不想要后者;它只会污染命名空间。
有趣的是,如果 tools.py
被调用 foo.py
你会得到你想要的:
mymod.foo()
(显然,这仅在每个文件只有一个函数的情况下有效。)
如何避免导入 tools
?请注意,将 foo()
放入 __init__.py
不是一个选项。 (实际上,有 很多 函数,例如 foo
绝对会使文件混乱。)
尝试将其放入您的 __init__.py
文件中:
from .tools import foo
del tools
mymod.tools
属性的存在对于维持导入系统的正常功能至关重要。 Python 导入的正常不变量之一是,如果模块 x.y
在 sys.modules
中注册,则 x
模块有一个 y
属性引用x.y
模块。否则,
import x.y
x.y.y_function()
break,根据 Python 版本,甚至
from x import y
可以破解。即使您不认为自己正在做任何会破坏的事情,其他工具和模块也依赖于这些不变量,并且尝试删除该属性会导致大量兼容性问题,而这些问题根本不值得。
试图让 tools
不出现在你的 mymod
模块的命名空间中有点像试图不让 "private" (leading-underscore) 属性出现在你的模块中对象的命名空间。这不是 Python 设计的工作方式,并且试图强迫它以这种方式工作会导致比它解决的问题更多的问题。
leading-underscore 约定不仅仅适用于实例变量。您可以使用前导下划线标记您的 tools
模块,并将其重命名为 _tools
。这将防止它被 from mymod import *
导入获取(除非你明确地将它放在 __all__
列表中),并且它会改变 IDE 和 linters 处理直接访问它的尝试的方式。
您没有导入 tools
模块,它只是在您导入包时可用:
import mymod
您将有权访问 __init__
文件中定义的所有内容以及此包的所有模块:
import mymod
# Reference a module
mymod.tools
# Reference a member of a module
mymod.tools.foo
# And any other modules from this package
mymod.tools.subtools.func
当你在 __init__
中导入 foo
时,你只是让 foo
在那里可用,就像你在那里定义了它一样,当然你在 [=15] 中定义了它=] 这是一种组织包的方式,所以现在既然你在 __init__
中导入了它,你就可以:
import mymod
mymod.foo()
或者你可以单独导入foo
:
from mymod import foo
foo()
但是您可以导入 foo
而无需在 __init__
中使用它,您可以执行以下与上面的示例完全相同的操作:
from mymod.tools import foo
foo()
您可以使用这两种方法,它们都是正确的,在所有这些示例中您不是 "cluttering the file" 正如您所看到的那样,使用 mymod.tools.foo
访问 foo
是命名空间的,因此您可以在其他模块中定义了多个 foo
。
我有一个具有以下结构的 Python 模块:
mymod/
__init__.py
tools.py
# __init__.py
from .tools import foo
# tools.py
def foo():
return 42
现在,当 import mymod
时,我看到它有以下成员:
mymod.foo()
mymod.tools.foo()
不过我不想要后者;它只会污染命名空间。
有趣的是,如果 tools.py
被调用 foo.py
你会得到你想要的:
mymod.foo()
(显然,这仅在每个文件只有一个函数的情况下有效。)
如何避免导入 tools
?请注意,将 foo()
放入 __init__.py
不是一个选项。 (实际上,有 很多 函数,例如 foo
绝对会使文件混乱。)
尝试将其放入您的 __init__.py
文件中:
from .tools import foo
del tools
mymod.tools
属性的存在对于维持导入系统的正常功能至关重要。 Python 导入的正常不变量之一是,如果模块 x.y
在 sys.modules
中注册,则 x
模块有一个 y
属性引用x.y
模块。否则,
import x.y
x.y.y_function()
break,根据 Python 版本,甚至
from x import y
可以破解。即使您不认为自己正在做任何会破坏的事情,其他工具和模块也依赖于这些不变量,并且尝试删除该属性会导致大量兼容性问题,而这些问题根本不值得。
试图让 tools
不出现在你的 mymod
模块的命名空间中有点像试图不让 "private" (leading-underscore) 属性出现在你的模块中对象的命名空间。这不是 Python 设计的工作方式,并且试图强迫它以这种方式工作会导致比它解决的问题更多的问题。
leading-underscore 约定不仅仅适用于实例变量。您可以使用前导下划线标记您的 tools
模块,并将其重命名为 _tools
。这将防止它被 from mymod import *
导入获取(除非你明确地将它放在 __all__
列表中),并且它会改变 IDE 和 linters 处理直接访问它的尝试的方式。
您没有导入 tools
模块,它只是在您导入包时可用:
import mymod
您将有权访问 __init__
文件中定义的所有内容以及此包的所有模块:
import mymod
# Reference a module
mymod.tools
# Reference a member of a module
mymod.tools.foo
# And any other modules from this package
mymod.tools.subtools.func
当你在 __init__
中导入 foo
时,你只是让 foo
在那里可用,就像你在那里定义了它一样,当然你在 [=15] 中定义了它=] 这是一种组织包的方式,所以现在既然你在 __init__
中导入了它,你就可以:
import mymod
mymod.foo()
或者你可以单独导入foo
:
from mymod import foo
foo()
但是您可以导入 foo
而无需在 __init__
中使用它,您可以执行以下与上面的示例完全相同的操作:
from mymod.tools import foo
foo()
您可以使用这两种方法,它们都是正确的,在所有这些示例中您不是 "cluttering the file" 正如您所看到的那样,使用 mymod.tools.foo
访问 foo
是命名空间的,因此您可以在其他模块中定义了多个 foo
。