2009-06-22 2 views
4

mod1.pyPython - когда требуется «импорт»?

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++ фона у меня было чувство, что это было необходимо импортировать модуль, содержащий определение класса Вселенной, прежде чем функция show_answer будет работать. То есть все должно было быть объявлено до того, как оно может быть использовано.

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

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

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

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

UPDATE: Спасибо за ответы на все вопросы, я думаю, что я должен прояснить мой вопрос сейчас:

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

+0

Чтобы ответить вам второй вопрос: нет, это динамическое. Он смотрит в вещь .__ dict__ для записи «ответа». Grep для «экземпляров класса» по адресу http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy – NicDumZ

ответ

4

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

1

Подумайте, что импорт больше похож на компоновщик.
с «импортными Mod2» вы просто говорить питона, что он может найти эту функцию в файле mod2.py

+2

Помните, что импорт происходит во время выполнения. Нет времени компиляции.Вы не объявляете все. Вы просто предоставляете способ разрешения имен. –

+0

Это уместно? Импорт - это просто указание виртуальной машине, для которой требуется посмотреть файл, при этом он не имеет никакого значения. –

+1

Подумайте об импорте в основном в виде комбинации #include для всего файла и изменения имен xxx -> mod.xxx –

6

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

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

+0

Действительно, хотя есть способы обойти это - класс mod1 может передать объект Universe в mod2, который может при необходимости создать больше экземпляров. –

1

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

+0

Нет, это происходит не потому, что импорт происходит до определения класса Universe. –

+0

Я несколько исказил то, что имел в виду, я исправлю это, чтобы сказать. – AlbertoPL

1

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

+0

Действительно, и см. Дополнительную информацию в ссылке в моем ответе. –

+0

Ой, да, ты прав. Я немного урезал код примера. Попытайтесь представить себе, что вселенная класса находится в модуле, все на своем собственном! –

1

В самом деле, согласно this explanation, круговое import не будет работать так, как вы хотите, чтобы работать: если вы раскомментировать import mod1, то второй модуль еще не знает о Universe.

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

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

Да, извините за круговой импорт, это была ошибка с моей стороны. Мой вопрос был, хотя: правда ли, что mod2 * не * должен знать, как реализована Вселенная? Я мог бы просто передать объект ExamQuestion для show_answer только до тех пор, пока у него есть метод answer()? –

+0

Да. Так что, это. Я думаю, что это упрощает понимание Python. Хотя некоторые люди жалуются на это, это позволяет совершить ошибку, вызвав метод неправильного типа, но я пока этого не вижу. –

1

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

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

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

eval("mod2.py") 

такая же, как ..

from mod2 import * 

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

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

import mod2 

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

mod2.show_answer 

Правильно ли я думать [импорт в mod2.py] не является n ecessary?

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

+1

Ну, eval (open (...). Read()) ближе к тому, что вы имели в виду, я думаю ... –

+0

Это будет exec (compile (open ("m2.py"). Read(), «m2.py», «exec»)) – dbr

Смежные вопросы