2015-03-31 1 views
1

У меня есть следующий файл app.pyОператор импорта Python также автоматически импортирует зависимости?

class Baz(): 
    def __init__(self, num): 
     self.a = num 
     print self.a 

def foo(num): 
    obj = Baz(num) 

и второй файл main.py

from app import foo 
foo(10) 

Запуск файла python main.py дает правильный вывод.

Теперь во втором файле я просто импортирую функцию не класса, хотя для успешного выполнения моей функции также нужен класс.

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

ответ

2

Как уже упоминалось @DavidZ, весь файл Python компилируется при импорте. Но другая особенность возникает, когда тело функции анализируется, функция знает, какие переменные она должна искать в локальной области и какие переменные она должна искать в глобальной области (ну, кроме того, есть и свободные переменные).

>>> import dis 
>>> dis.dis(foo) 
    7   0 LOAD_GLOBAL    0 (Baz) 
       3 LOAD_FAST    0 (num) 
       6 CALL_FUNCTION   1 
       9 STORE_FAST    1 (obj) 
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE 

Итак, Baz должны быть выбраны из глобального масштаба.

Но как определить эту глобальную область при импорте app.py в другой файл ?

Ну, каждая функция имеет специальный атрибут __globals__, который содержит его фактическое глобальное пространство имен. Следовательно, это источник Baz:

>>> foo.__globals__['Baz'] 
<class __main__.Baz at 0x10f6e1c80> 

Так, словарь модуль приложения и foo.__globals__ указывают на тот же объект:

>>>sys.modules['app'].__dict__ is foo.__globals__ 
True 

В связи с этим, даже если вы определить другую переменную с именем Baz в main.py после импорта foo он по-прежнему будет иметь доступ к фактическому Baz.

data-model page От:

__globals__ func_globals:

Ссылка на словарь, который содержит глобальные переменные функция в - глобальном пространстве имен модуля, в котором функция была определена.

+0

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

+0

@KartikAnand Python будет компилировать его только один раз в файл '.pyc', позже импорт просто выберет байт-код из того же файла' .pyc', пока вы снова не обновите файл '.py'. –

+0

Итак, если я явно не импортирую 'Baz', могу ли я создать экземпляр, получив его от' __globals__', прикрепленного к функции? –

1

Python автоматически не выполняет какие-либо из этих действий.

Когда вы импортируете что-то из модуля (в этом случае модуль app), Python сначала запускает весь код в соответствующем файле (app.py). Код в файле app.py, который Вы написали делает две вещи:

  1. определяют класс Baz
  2. определяют функцию foo

, когда функция foo пробегов, Python ищет Baz в модуль, который foo является частью, и только там. (Ну, он также проверяет локальные переменные, определенные в функции foo, но у вас нет ни одного из них, кроме obj.) В частности, он ищет app.Baz. Если вы изменяете ваш main.py сделать такой же поиск:

from app import foo 
foo(10) 
import app # same app that was already imported 
print app.Baz 

вы увидите, что app.Baz класс вы определили в app.py.

Если вы поместили определение класса Baz в еще один файл, и если вы не импортируете этот файл, Python его не запустит. Это показывает, что Python делает не автоматически импортирует зависимости. В частности, предположим, что app.py содержит

def foo(num): 
    obj = Baz(num) 

и baz.py содержит

class Baz(): 
    def __init__(self, num): 
     self.a = num 
     print self.a 

и main.py неизменна. Вы получите сообщение об ошибке, поскольку Python не выполнил код для определения класса Baz.

+0

Я знаю об определении. Когда он запускает файл, сохраняет ли он часть определения класса в какой-либо форме в текущем файле? –

+0

Посмотрите, поможет ли мое редактирование что-нибудь –