为什么有时我可以使用嵌套模块中的函数而无需导入整个路径?

ruo*_*ola 8 python import module package python-import

我想知道这两种情况有什么区别?模块的内部结构是否有所不同?

那么为什么这个有效:

>>> import numpy
>>> numpy.random.RandomState
<class 'numpy.random.mtrand.RandomState'>
Run Code Online (Sandbox Code Playgroud)

但在我也导入嵌套模块之前,这个不起作用:

>>> import tkinter
>>> tkinter.ttk.Spinbox
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'tkinter' has no attribute 'ttk'
>>> import tkinter.ttk
>>> tkinter.ttk.Spinbox
<class 'tkinter.ttk.Spinbox'>
Run Code Online (Sandbox Code Playgroud)

我认为这一定与每个模块中的文件有关__init__.py,但是一个具体的实现示例会很有帮助。

ruo*_*ola 4

这种导入行为可以通过导入各个__init__.py文件中的深层类来实现。numpy这是项目结构的快速演示,其工作方式与真实项目和包几乎完全相同tkinter

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 numpy\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 random\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 mtrand.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tkinter\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 ttk.py\n
Run Code Online (Sandbox Code Playgroud)\n

numpy/__init__.py:

\n
from .random import RandomState\n
Run Code Online (Sandbox Code Playgroud)\n

numpy/random/__init__.py:

\n
from .mtrand import RandomState\n
Run Code Online (Sandbox Code Playgroud)\n

numpy/random/mtrand.py:

\n
class RandomState:\n    pass\n
Run Code Online (Sandbox Code Playgroud)\n

tkinter/__init__.py:

\n
\n

tkinter/ttk.py:

\n
class Spinbox:\n    pass\n
Run Code Online (Sandbox Code Playgroud)\n

main.py:

\n
import numpy\nimport tkinter\n\nprint(numpy.random.RandomState)\n\ntry:\n    print(tkinter.ttk.Spinbox)\nexcept AttributeError as e:\n    print("Error:", e)\n    import tkinter.ttk\n    print(tkinter.ttk.Spinbox)\n
Run Code Online (Sandbox Code Playgroud)\n
\n

输出:

\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 numpy\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 random\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 mtrand.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tkinter\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 ttk.py\n
Run Code Online (Sandbox Code Playgroud)\n
\n