У меня очень простой пример:
#!/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 и С++ файлы заголовков позаботятся об этом. В Паскале вы должны иметь определения имени до их использования.
Предположим, например, что у вас это в 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 script, который утверждает, что функции могут иметь форвардные определения других имен подпрограмм, но главный код не может?
Редактирование и заключение
После некоторых энергичных комментариев и некоторых исследований с моей стороны я пришел к выводу, что мой вопрос действительно больше о том, как разрешаются имена и как пространства имен, области и модули определены в Python.
Из каротинга:
"вызываемый должен быть определен до его вызова в текущем пространстве имен." и эта ссылка по областям и именам
Из S.Lott:
"Когда имя используется в кодовом блоке, оно разрешается с использованием ближайшей охватывающей области". и эта ссылка в срок выполнения Python script.
Из документов Python:
"Область определяет видимость имени внутри блока". Из Модель выполнения Python
"Модуль может содержать исполняемые операторы, а также определения функций". в подробнее о модулях
"На самом деле определения функций также выполняются" операторы ", выполнение функции уровня модуля входит в имя функции в глобальной таблице символов модулей". в сноске к нему.
И моя собственная реализация (Duh!), которая:
-
Каждый исходный файл Python рассматривается как "модуль" Python: "Модуль - это файл, содержащий определения и утверждения Python".
-
В отличие от Perl (с которым у меня больше опыта) Python выполняет модули по мере их чтения. Следовательно, сбой сразу исполняемого оператора ссылается на функцию, еще не определенную в том же модуле.