Я имею дело с некоторым кодом Python, автоматически сгенерированным для меня. Я не хочу вручную редактировать эти файлы Python и следовательно этот вопрос/проблему:
foo.py:
def foo():
print "foo"
boo.py:
def boo():
foo.foo() # <-- global name 'foo' not defined
print "boo"
bar.py:
import foo
import boo
def bar():
boo.boo()
print "bar"
Выполнение:
python.exe bar.py
дает ошибку это boo
не нашел foo
. Но панель импортирует обоих foo
& boo
. Не был должен foo
будьте автоматически доступны boo
?
Существует ли способ сделать так? Как сказано boo.py автоматически сгенерирован для меня, и я не хочу добавлять нечто импорта к boo.py.
Спасибо.
Но bar импортирует и foo, и boo. Разве foo не должно быть автоматически доступным для boo?
Нет, не должен: import
, как и любой другой способ связать имя, связывает это имя в одной конкретной области видимости, а не "во всех областях видимости, в которых оно может понадобиться".
Есть ли способ сделать это? Как было сказано boo.py автоматически генерируется для меня, и я хочу избежать добавления import foo в boo.py
Есть один очень плохой хак - я бы не хотел жить с ним (я бы предпочел потратить свою энергию на то, чтобы исправить этот полностью сломанный генератор кода, который делает boo.py
- если в нем есть такая огромная ошибка, как отсутствие критически важного необходимого импорта, то какие еще ужасы он может иметь в запасе?! ), но, эй, это не мои похороны...;-)
Пусть bar.py
начнет...:
import foo
import boo
import __builtin__
__builtin__.foo = foo
Таким образом вы сделали идентификатор foo
"фальшивым, искусственным встроенным именем" (единственный вид имени, который доступен из любой области видимости, если только его не затеняют другие промежуточные привязки имени
в более близких областях), ссылающееся на модуль foo
.
НЕ рекомендуемая процедура, просто временное обходное решение для ужасной, бросающейся в глаза ошибки в генераторе кода, который собирает boo.py
. Исправьте эту ошибку, и вы сможете удалить этот хак как можно скорее!
вы должны импортировать foo в boo
boo.py
import foo
def boo():
foo.foo() # <-- global name 'foo' not defined
print "boo"
bar.py
import boo
def bar():
boo.boo()
print "bar"
Нет. Если вы хотите, чтобы foo
был доступен в boo
, вам необходимо импортировать его в boo
. import foo
, который находится в bar
, делает доступным только foo
в модуле bar
.
В общем, оператор import
в Python похож на определение переменной. На самом деле вы можете думать об этом так: мысленно замените
import boo
на
boo = __import__('boo')
( __ import __
- встроенная функция интерпретатора Python, которая либо импортирует модуль, либо ищет ссылку на существующий модуль, если он уже импортирован и возвращает эту ссылку)
Все, что автоматически генерирует boo.py
, делает это неправильно. Он должен добавить import foo
где-нибудь в этот файл. Вы можете обойти это, сделав это в bar.py
:
import foo
import boo
boo.foo = foo
, но на самом деле вам не нужно этого делать. (Я повторяю то, что сказал Алекс Мартелли о том, что такого рода вещи являются огромным взломом)
Каждый модуль имеет собственное пространство имен. Итак, чтобы boo.py увидел что-то из внешнего модуля, boo.py должен сам импортировать это.
Можно написать язык, на котором пространства имен располагаются так, как вы ожидаете: это называется динамической областью видимости. Некоторые языки, такие как исходный lisp, ранние версии perl, postscript и т. Д., Используют (или поддерживают) динамическую область видимости.
В большинстве языков вместо этого используется лексическая область видимости. Оказывается, это гораздо более удобный способ работы языков: таким образом модуль может рассуждать о том, как он будет работать, на основе своего собственного кода, не беспокоясь о том, как он был вызван.
См. Дополнительную информацию в этой статье: http://en.wikipedia.org/wiki/Scope_%28programming%29