Почему иногда я могу использовать функции из вложенных модулей, не импортируя весь путь? - PullRequest
3 голосов
/ 19 февраля 2020

Мне было интересно, в чем разница между этими двумя случаями? Внутренняя структура модулей как-то отличается?

Так почему этот работает:

>>> import numpy
>>> numpy.random.RandomState
<class 'numpy.random.mtrand.RandomState'>

Но этот не будет работать, пока я не импортирую вложенный модуль:

>>> 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'>

Я думаю, что это должно быть как-то связано с файлами __init__.py в каждом модуле, но конкретный пример реализации будет полезен.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2020

Такое поведение импорта может быть достигнуто путем импорта глубокого класса в соответствующие файлы __init__.py. Вот краткая демонстрация структуры проекта, которая работает почти так же, как действительные пакеты numpy и tkinter:

.
├── __init__.py
├── main.py
├── numpy
│   ├── __init__.py
│   └── random
│       ├── __init__.py
│       └── mtrand.py
└── tkinter
    ├── __init__.py
    └── ttk.py

numpy/__init__.py:

from .random import RandomState

numpy/random/__init__.py:

from .mtrand import RandomState

numpy/random/mtrand.py:

class RandomState:
    pass

tkinter/__init__.py:


tkinter/ttk.py:

class Spinbox:
    pass

__init__.py:


main.py:

import numpy
import tkinter

print(numpy.random.RandomState)

try:
    print(tkinter.ttk.Spinbox)
except AttributeError:
    print("Caught an exception!")
    import tkinter.ttk
    print(tkinter.ttk.Spinbox)

Выход:

<class 'numpy.random.mtrand.RandomState'>
Caught an exception!
<class 'tkinter.ttk.Spinbox'>
0 голосов
/ 19 февраля 2020

По умолчанию, когда вы загружаете «пакет» (который на самом деле является просто каталогом с файлом __init__.py, Python загружает только файл __init__.py.

В этом файле, если вы Если вы хотите, вы можете автоматически загружать другие вещи, такие как модули (другие файлы .py) и даже другие пакеты (каталоги с __init __. py)

Таким образом, причина, по которой эти библиотеки различаются, скорее всего из-за разницы в как настраиваются файлы __init__.py.

Например, я создал пакет с одним модулем. У меня есть модуль, импортированный файлом __init__.py, чтобы он автоматически загружался.

...