У меня очень простой пример:
#!/usr/bin/env python
#a() # 1: NameError: name 'a' is not defined
#b() # 1: NameError: name 'b' is not defined
#c() # 1: NameError: name 'c' is not defined
def a():
c() # note the forward use here...
#a() #2: NameError: global name 'c' is not defined
#b() #2: NameError: name 'b' is not defined
#c() #2: NameError: name 'c' is not defined
def b():
a()
#a() #3: NameError: global name 'c' is not defined
#b() #3: NameError: global name 'c' is not defined
#c() #3: NameError: name 'c' is not defined
def c():
pass
a() # these all work OK...
b()
c()
У меня есть 3 функции с именами a()
, b()
и c()
, определенные в исходном файле Python в алфавитном порядке. Тело каждого определения функции является вызовом одной из других функций. Из моих комментариев вы можете видеть, что у меня должен быть начальный вызов первой из этих функций НИЖЕ их определений (в текстовом файле), но вам не обязательно нужно определение функции над другой функцией, которая ее вызывает.
Конечно, обычной практикой является использование первого исполняемого кода ниже всех определений функций (в Python и многих других языках), и теперь я понимаю, почему. В C и C ++ заголовочные файлы позаботятся об этом. В Паскале вы должны иметь определения имен до их использования.
Предположим, например, что у вас есть это в Python:
def a(a_arg): c(a_arg)
def b(b_arg): a()
def c(a_arg,b_arg): b(b_arg)
a(1)
Он будет некорректно работать с TypeError: c() takes exactly 2 arguments (1 given)
во время выполнения, где другие ошибки - во время компиляции. (в C это скомпилируется, затем загадочным образом завершится ошибкой ...)
В Perl, поскольку имена подпрограмм обычно разрешаются во время выполнения, вы можете иметь определения и код Perl в любом порядке:
#!/usr/bin/env perl
a();
b();
c();
sub a{ c(); }
sub b{ a(); }
sub c{ return; }
В C это либо ошибка, либо предупреждение (зависит от реализации), чтобы использовать функцию, которая не была прототипирована и не должна игнорироваться.
Вы можете иметь это:
void a(void) { c(); } /* implicitly assumed to be int c(...) unless prototyped */
void b(void) { a(); }
void c(void) { return; }
int main(void) {
a();
return EXIT_SUCCESS;
}
Мои предположения и путаница заключаются в следующем: если Python не разрешает имена подпрограмм до времени выполнения, почему фаза компиляции исходного кода завершается неудачно с предварительным объявлением имен подпрограмм, которые еще не определены? Задокументировано ли где-то (кроме наблюдения за другим кодом), что вы не можете иметь код в исходном файле выше определений подпрограмм?
Похоже, что в Python есть элементы с динамическим разрешением имен (использование c()
в a()
до его определения ниже в исходном файле) и элементы статического разрешения имен (ошибка Python для вызова a()
, если он находится над его определением в исходном файле.)
Существует ли Python-версия ЭТОГО ДОКУМЕНТА , которая охватывает жизненный цикл исполняемого файла Perl и как разрешаются имена между интерпретацией исходного файла и временем выполнения?
Есть ли где-то определенное описание порядка определений для скрипта Python, в котором говорится, что функции могут иметь прямые определения других имен подпрограмм, а основной код - нет?
Редактирование и заключение
После некоторых энергичных комментариев и некоторых исследований с моей стороны, я пришел к выводу, что мой вопрос действительно больше о том, как разрешаются имена и как определяются пространства имен, области действия и модули в Python.
С карот-топ :
«вызываемый объект должен быть определен до его вызова в текущем пространстве имен».
и эта ссылка в областях и именах
С S.Lott :
«Когда имя используется в блоке кода, оно разрешается с использованием ближайшей охватывающей области».
и эта ссылка на время выполнения скрипта Python.
Из документов Python:
«Область действия определяет видимость имени в блоке». Из модели Python Execution
"Модуль может содержать исполняемые операторы, а также определения функций." в подробнее о модулях
«Фактически определения функций также являются« операторами », которые« выполняются »; выполнение функции уровня модуля заносит имя функции в глобальную таблицу символов модуля». в сноске к этому.
И мое собственное понимание (Дух!), Что:
Каждый исходный файл Python рассматривается Python как «модуль»: «Модуль - это файл, содержащий определения и операторы Python».
В отличие от Perl (с которым у меня больше опыта) Python выполняет модули по мере их чтения. Отсюда сбой непосредственно исполняемого оператора, ссылающегося на функцию, еще не определенную в том же модуле.