Python - когда требуется импорт? - PullRequest
4 голосов
/ 22 июня 2009

mod1.py

import mod2

class Universe:
    def __init__(self):
        pass
    def answer(self):
        return 42

u = Universe()
mod2.show_answer(u)

mod2.py

#import mod1 -- not necessary
def show_answer(thing):
    print thing.answer()

Исходя из фона C ++, у меня было ощущение, что необходимо импортировать модуль, содержащий определение класса Universe, прежде чем будет работать функция show_answer. То есть все должно быть объявлено, прежде чем его можно будет использовать.

Правильно ли я считаю, что в этом нет необходимости? Это утка печатает, верно? Так что, если импорт не требуется для просмотра методов класса, я бы по крайней мере нуждался в нем для определения самого класса и функций верхнего уровня модуля?

В одном скрипте, который я написал, я даже дошел до написания базового класса для объявления интерфейса с набором методов, а затем получения конкретных классов для наследования этого интерфейса, но я думаю, что я понял это сейчас просто неправильно в Python, и проверяется ли у объекта определенный метод во время выполнения в момент, когда сделан вызов?

Я понимаю, что Python , поэтому гораздо более динамичен, чем C ++, мне потребовалось время, чтобы увидеть, как мало кода на самом деле нужно писать!

Мне кажется, я знаю ответ на этот вопрос, но я просто хотел получить разъяснения и убедиться, что я на правильном пути.

ОБНОВЛЕНИЕ: Спасибо за все ответы, я думаю, что я должен уточнить мой вопрос сейчас:

Нужен ли mod2.show_answer () импорт (любого описания), чтобы узнать, что у этого объекта есть метод answer (), или он определяется динамически во время выполнения?

Ответы [ 7 ]

6 голосов
/ 22 июня 2009

В этом случае вы правы: show_answer () задается объект, для которого он вызывает метод answer. Поскольку объект, данный для show_answer (), имеет такой метод, не имеет значения, откуда этот объект.

Однако, если вы хотите создать экземпляр Universe внутри mod2, вам придется импортировать mod1, потому что Universe нет в пространстве имен mod2, даже после того, как mod2 был импортирован mod1.

4 голосов
/ 22 июня 2009

import это все об именах - в основном "голые имена", которые связаны на верхнем уровне (глобальный уровень AKA, имена уровня модуля AKA) в определенном модуле, скажем mod2. Когда вы выполните import mod2, вы получите пространство имен mod2 в качестве доступного имени (верхний уровень в вашем собственном модуле, если вы делаете import как верхний уровень, как это чаще всего встречается; local import внутри функции сделает mod2 локальной переменной этой функции и т. д.); и поэтому вы можете использовать mod2.foobar для доступа к имени foobar, которое привязано к верхнему уровню в mod2. Если вам не нужен доступ к таким именам, вам не нужно import mod2 в своем собственном модуле.

1 голос
/ 22 июня 2009

Я не очень разбираюсь в C ++, поэтому не могу напрямую сравнить его, но ..

import в основном загружает другой скрипт Python (mod2.py) в текущий скрипт (верхний уровень mod1.py). Это не просто ссылка, это ближе к eval

Например, в Python'ish псевдо-код:

eval("mod2.py")

совпадает с ..

from mod2 import *

.. он выполняет mod2.py и делает определенные функции / классы доступными в текущем скрипте.

Оба приведенных выше фрагмента позволят вам вызвать show_answer() (ну, eval не совсем так работает, поэтому я назвал это псевдокодом!)

import mod2

.. в основном то же самое, но вместо того, чтобы вводить все функции на «верхний уровень», он переводит их в модуль mod2, поэтому вы вызываете show_answer, выполнив ..

mod2.show_answer

Правильно ли я думаю, что [импорт в mod2.py] не нужен?

Абсолютно. Фактически, если вы попытаетесь импортировать mod1 из mod2, вы получите циклическую ошибку зависимости (поскольку mod2 затем пытается импортировать mod1 и т. Д.)

1 голос
/ 22 июня 2009

Фактически, согласно этому объяснению , циркуляр import не будет работать так, как вы хотите, чтобы он работал: если вы раскомментируете import mod1, второй модуль все равно не будет знать о Universe.

Я думаю, это вполне разумно. Если оба ваших файла нуждаются в доступе к типу какого-либо определенного объекта, например Universe, у вас есть несколько вариантов:

  • если ваша программа небольшая, просто используйте один файл
  • если он большой, вам нужно решить, нужно ли вашим файлам знать, как реализован Universe, возможно, передача объекта еще не известного типа в show_answer это нормально
  • если это не работает для вас, во что бы то ни стало поместите Universe в отдельный модуль и загрузите его первым.
1 голос
/ 22 июня 2009

На самом деле, в этом случае импорт mod1 в mod2.py должен не работать.
Разве это не создаст круговую ссылку?

1 голос
/ 22 июня 2009

import в Python загружает модуль в заданное пространство имен. По сути, это так, как если бы def show_answer действительно существовал в модуле mod1.py. Из-за этого mod2.py не нужно знать класс Universe, и, следовательно, вам не нужно импортировать mod1 из mod2.py.

1 голос
/ 22 июня 2009

Представьте, что импорт больше похож на компоновщик.
С помощью "import mod2" вы просто указываете python, что он может найти функцию в файле mod2.py

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...