I have a very simple example:
#!/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()
I have 3 functions named a()
, b()
and c()
defined in a Python source file in alphabetical order. The body of each function definition is a call to one of the other functions. You can see by my comments that I have to have the initial call to the first of these functions BELOW their definitions (in the text file), but you do not necessarily need definition of a function above another function that calls it.
Certainly it seems to be common practice to have the first executable code below all the function definitions (in Python and many other languages), and now I can see why. In C and C++, header files take care of this. In Pascal you must have name definitions prior to their use.
Assume, for example, that you have this in Python:
def a(a_arg): c(a_arg)
def b(b_arg): a()
def c(a_arg,b_arg): b(b_arg)
a(1)
It will fail properly with TypeError: c() takes exactly 2 arguments (1 given)
at runtime where the other errors are compile time. (in C, this would compile then fail mysteriously...)
In Perl, since subroutines names are USUALLY resolved at run time, you can have Perl definitions and code in any order:
#!/usr/bin/env perl
a();
b();
c();
sub a{ c(); }
sub b{ a(); }
sub c{ return; }
In C, it is either an error or a warning (implementation dependent) to use a function that has not been prototyped and shouldn't be ignored.
You can have this:
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;
}
My assumptions and confusion is this: If Python does not resolve subroutines names until runtime, why does the source compile phase fail with the forward declaration of subroutine names that have not been defined yet? Is it documented somewhere (other than by observation of other code) that you cannot have code in a source file above definitions of subroutines?
It seems that Python has elements of dynamic name resolution (the use of c()
in a()
prior to its definition below in the source file) and elements of static name resolution (the failure of Python to run the call to a()
if placed above its definition in the source file.)
Is there a Python version of THIS DOCUMENT that covers the lifecycle of a Perl executable and how names are resolved between source file interpretation and runtime?
Is there a definitive description somewhere on the order of definitions for a Python script that states functions can have forward definitions of other subroutine names but main code cannot?
Edit and conclusion
After some spirited comments, and some research on my part, I have concluded that my question is really more about how names are resolved, and how namespaces, scopes and modules are defined in Python.
From carot-top:
"a callable must be defined before it is called in the current namespace."
and this link on scopes and names
From S.Lott:
"When a name is used in a code block, it is resolved using the nearest enclosing scope."
and this link to the execution life of a Python script.
From the Python documents:
"A scope defines the visibility of a name within a block." From the Python Execution model
"A module can contain executable statements as well as function definitions." in more about modules
"In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function enters the function name in the module’s global symbol table." in the footnote thereto.
And my own realization (Duh!) that:
Every Python source file is treated as a "module" by Python: "A module is a file containing Python definitions and statements."
Unlike Perl (which I have more experience with) Python executes modules as they are being read. Hence the failure of a immediately executable statement referring to a function not yet defined in the same module.
See Question&Answers more detail:
os