25

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:

  1. Every Python source file is treated as a "module" by Python: "A module is a file containing Python definitions and statements."

  2. 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.

Community
  • 1
  • 1
dawg
  • 98,345
  • 23
  • 131
  • 206
  • "forward definitions"? What does that mean? Are you asking about forward "references"? The answer is trivially yes. I'm sorry, but the question confuses me. – S.Lott Feb 10 '11 at 00:16
  • I used "forward definition" because of the original question being about when and where `def c()` is used in relationship to `def a()` and in relationship to code that immediately executes. In C and Pascal, it would be called a "forward" or "external" declaration by a function prototype in a header or otherwise prior to use. In Python it seems to matter sometimes but not others. Once again: **my question is where is the documentation that covers this?** What can be resolved at runtime and what cannot be? I have read the Python web site docs. – dawg Feb 10 '11 at 17:24
  • @S.Lott: I always thought of "forward reference" as the term used in a two pass compiler which Python is not. – dawg Feb 10 '11 at 17:36
  • @S.Lott: You say the answer is "trivially yes." As an additional example of my question: why can you have `def a(): return Global_B` with Global_B being a forward reference / declaration to a statement below or elsewhere but you cannot have a forward reference to the statement that defines a function outside of a function? That is not "trivial." It is either a random side effect or formally defined in the language specification in a document that I have not read. – dawg Feb 10 '11 at 17:39
  • @drewk: I'm not sure what more you could be looking for. Name resolution happens when the name is encountered. There cannot be a "forward" references because there are no "declarations" in any form. Your question is very confusing because it uses non-Python concepts like "declaration" and "forward". – S.Lott Feb 10 '11 at 18:22
  • @S.Lott: I stated what I was looking for: A Python version of that Perl document. – dawg Feb 10 '11 at 18:55
  • @drewk: In addition to that request, the question is full of non-python concepts that makes it very hard to understand the question or determine what you **need**. Python is not Perl. Continuing to demand a Python document that magically matches a document for an utterly different language confuses me. The languages don't match. I can't see how a document for one language must have matching document in another language. – S.Lott Feb 10 '11 at 19:07
  • @S.Lott: It apparent that you know Python much better that I do. I have been using Python 3 months and I have been using C and Perl for years. That I would fall back on concepts that are familiar to me should not be surprising. If you were learning something you don't know, the same may happen to you. I did not "demand" anything. I asked a question on a question and answer site. You kept asking me to clarify; I offered that document as an example of what I was looking for. Regardless of the language, concepts can be similar. Isn't this site about asking questions and getting answers? – dawg Feb 11 '11 at 16:36
  • @drewk: "Regardless of the language, concepts can be similar". Sorry, I haven't found this to be true. I apologize, but of the languages I know (including C, Java and Python) the concepts don't travel well among languages. The repetition of non-Python concepts in a Python question confuses me. I apologize for being dense, but I just can't map the concepts like "declaration" to a language that lacks them. – S.Lott Feb 11 '11 at 16:44
  • @S.Lott: "concepts don't travel well among languages" Regardless of the language, there needs to be some concept of name resolution to code and data. The behavior I was seeing in Python had elements that implied dynamic, run-time name resolution and other behaviors that implied static resolution. I am just trying to understand how Python resolves names. I have concluded it really more about how Python loads modules, and the individual namespace associated with the executing scope. If I knew all that when I asked the question -- I would not have asked the question. – dawg Feb 11 '11 at 17:45
  • @drewk: "concept of name resolution". Agreed. Words like "forward declaration", however, confused me in a Python context. Lacking declarations, the question wasn't sensible. If the question was about "name resolution", it might have been a little more clear. – S.Lott Feb 11 '11 at 18:06
  • @S.Lott: I made the edits you suggested. Thanks for your help! – dawg Feb 11 '11 at 20:14

5 Answers5

28

The order of definitions is simply "everything has to be defined before you call it". That's pretty much it.

edit (to include answer in comments, elucidated):

The reason something like

def call_a():
    a()

def a():
    pass

call_a()

works when you've got a() in call_a() before a is even defined as a function is because Python only actually looks up values for symbols on an as-needed basis. When call_a is evaluated, the a() call is basically stored as bytecode instructions to "look up what a is and call it" when the time comes, which isn't until you get down to the actual invocation of call_a() at the bottom.

Here is what the disassembled bytecode of call_a looks like (via dis.dis):

Disassembly of call_a:
  2           0 LOAD_GLOBAL              0 (a)
              3 CALL_FUNCTION            0
              6 POP_TOP
              7 LOAD_CONST               0 (None)
             10 RETURN_VALUE

So basically, when you hit call_a, it loads whatever is stored as a onto the stack, calls it as a function, and then pops the return value off before returning None, which is what implicitly happens for anything that doesn't explicitly return (call_a() is None returns True)

Daniel DiPaolo
  • 55,313
  • 14
  • 116
  • 115
  • But the example shows otherwise. You can call functions below your code so long as the main body has not executed. The definition of `a()` with `c()` below would fail in C. – dawg Feb 08 '11 at 19:55
  • 3
    Yes, you are not actually invoking any of the functions until after they are defined. At the time it evaluates the function definition it just says "okay, I'll look up `c` in the symbol table when someone calls me" but at that moment it doesn't matter. – Daniel DiPaolo Feb 08 '11 at 19:59
  • 1
    @drewk: I guess you're confused by the fact that the body of a function doesn't matter until it's executed. You should, perhaps, review the Python language reference. The "definitive description" is trivial -- nothing matters until it's actually evaluated. – S.Lott Feb 08 '11 at 20:27
  • @S.Lott: Believe me, I did RTFM! I cannot find in the TFM these things: 1) [that there are no forward definitions or prototypes in Python](http://stackoverflow.com/questions/1590608/is-it-possible-to-forward-declare-a-function-in-python); 2) Python is kinda sorta evaluated top to bottom but the Real Rule is "define it before you call it" as Daniel DiPaolo stated. In C, Pascal, Perl, C++, Objective C, etc. the concept of name resolution at compile time and run-time are very formal. I have not seen that same treatment for Python. Hence the question. – dawg Feb 08 '11 at 21:19
  • @Daniel DiPaolo: Thanks! Your edited question (and some other SO posts) cleared it up enough for me to now worry about it any more. – dawg Feb 08 '11 at 21:20
  • @drewk: "concept of name resolution at compile time and run-time are very formal. I have not seen that same treatment for Python." What? Python has no compile time. Since it only has run-time, the name resolution is just as formal and just as well-defined. How can it be confusing? Please **update** your question to explain how the rule "evalation-time" can be confusing. – S.Lott Feb 08 '11 at 22:17
  • @S.Lott: ["Compile" is used frequently in the Python documentation](http://docs.python.org/glossary.html#term-bytecode) to cover the process of interpreting the source code into VM byte codes and pre interpreting modules into .pyc files. What do *you* call this process? You also took my quote out of context. I specifically was referring to "C, Pascal, Perl, C++, Objective C" I do not understand you comment / request of "Please update your question to explain how the rule "evalation-time" can be confusing." – dawg Feb 09 '11 at 00:55
  • @drewk: You're managing to conflate the trivial translation of Python syntax to byte code with the much more complex static language compilers that do name resolution. Please **update** the question to include what **you** think Python is doing. Because it isn't doing that. Your question is misleading because it **assumes** that name resolution happens somehow when a function is defined. Since that can't happen in Python, the question is misleading. – S.Lott Feb 09 '11 at 11:00
  • @S.Lott: I am sorry, but I am not understanding your issue. If I *knew* what I did not know and *knew* where to find it, I would research it and not bother anyone. Since I did not know why / how / with what paradigm Python is doing forward names, I asked. Isn't this a Q&A sight with patience for those who know less about this than you do? This falls into the "don't know what I don't know." I would like to understand HOW Python does forward name resolution. I asked for a pointer to the docs on this so I can RTFM. Help me understand how to rephrase that? I am not trying to mislead anyone. – dawg Feb 09 '11 at 23:25
  • @drewk: It's not what you knew. It's what you assumed. I apologize for suggesting that you should document your assumptions. – S.Lott Feb 09 '11 at 23:27
  • @S.Lott: OK, I **assumed** that somehow the definition of `c()` needed to be known at the time that `a()` was being processed by CPython. Since `a()` is above `c()` this is a forward definition. In C / Pascal / Objective C this would be a warning or error without a header file to prototype `c()` My question was: Is There a Python Version of [THIS DOCUMENT](http://oreilly.com/catalog/pperl3/chapter/ch18.html#AUTOID-22212) that covers the lifecycle of a Perl program. Perl resolves at runtime, so definitions can be in any order. **What does Python do and where can I read more** is 1 sentence. – dawg Feb 09 '11 at 23:48
  • @drewk: It helps to **update** the question with your assumptions. Other people who read the question need to know what you assumed in order to make sense of the question. I'm asking for you to put it in the question for others who find the question and want to understand it. – S.Lott Feb 09 '11 at 23:53
  • @S.Lott: If I understood correctly, I made the changes you requested. Thanks for the feed back. I sure THOUGHT I was being clear... – dawg Feb 10 '11 at 00:03
5

Following the various comments and struggling to understand some Perl concepts from a Python history, let me take a crack at this. Please reset your brain on some of things you learned in Perl. They do not apply in Python. (And vs vs...)

There are no forward declarations in Python. None. Technically, ALL functions are anonymous objects; they just happen to be bound to the name you used to define it. You can re-bind them at will.

The dictionary of these functions can be found using the locals() function like this:

>>> def a(): b()
... 
>>> locals()['a']
<function a at 0x100480e60>
>>> locals()['b']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'b'
>>> a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in a
NameError: global name 'b' is not defined

If Python required b() to be defined BEFORE writing a(), this would be a problem in the Python interpreter. You would need to write all you functions in strict order.

Since all builtin function names are just bounded names, you can easily override builtin functions:

>>> abs(-1)
1
>>> def abs(num): print "HA Fooled you!!!"
... 
>>> abs(-1)
HA Fooled you!!!
>>> abs=__builtins__.abs
>>> abs(-1)
1

It is much more difficult (but possible) to override built-ins in Perl. (The disadvantage here is a mistyped def [builtin]: can unintentionally override the built-in function without warning)

The best description I can refer you to for names and scope in Python is actually the tutorial on Classes -- section 9.2

There is not actually chapter and verse why def need to come before executable code because this is not a true statement. Consider:

#!/usr/bin/env python

def fake_a(): print " a fake"
a=fake_a
a()  
def a():  print "this is a()"
a()

Or even:

def a(): print " first a()"
a()  
def a():  print "second a()"
a()

What is true is that a callable must be defined before it is called in the current namespace. Hence, usually, above the point of being called by executable code in a source text file or module. Each function has its own namespace; calls to other functions not yet defined only fail when that function is called in that local and executing namespace -- when the callable is called from the namespace of the function. This why you can have what looks like a "forward declaration" in your example. The module call of a "forward" callable outside a function fails because the function def has not been executed yet so it is not in the current namespace.

Community
  • 1
  • 1
the wolf
  • 34,510
  • 13
  • 53
  • 71
  • 2
    I think you are right. I was thinking that the ability to refer to a function not yet defined implied some sort of forward reference ability. It is more a "rolling namespace" – dawg Feb 11 '11 at 16:25
3

This is exactly the same as in C/C++ etc. You can't use something until it exists. In C/C++ you can't refer to something until it has been declared. Remember that a Python file is processed from top to bottom so if you attempt to call a function or reference a variable that does not exist, then it fails.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 3
    "This is exactly the same as in C/C++" Well no it is isn't at all really. You can have a forward definition of a function in C but you cannot in Python. You can have run-time checking of functions in Python but cannot in C. You can have implicit prototypes in C and that is similar. – dawg Feb 08 '11 at 21:08
  • @drewk In other words, C/C++ are different from Python. Yes, I can't deny that. You are taking me too literally. You can't name a symbol in C/C++ until it has been declared. That's all I'm saying. – David Heffernan Feb 08 '11 at 21:13
1

http://docs.python.org/reference/executionmodel.html


When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.

The following constructs bind names: formal parameters to functions, import statements, class and function definitions (these bind the class or function name in the defining block), ...

That's it. There's no concept of "forward" or "reverse" or "declaration" or anything like that.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • @drewk: "Believe me, I did RTFM!". I'm puzzled how you could claim that and yet, somehow, not have found this. – S.Lott Feb 11 '11 at 16:31
  • 1
    While I said this was "helpful" it still does not answer the question I asked about why Python code can refer to an undefined subroutine inside a subroutine but not in the main code. Please point to where in that link it says that. You seem after me about this question. I have been respectfully trying to clarify. What's up? Seriously? I asked a question that compared what I saw in Python to what I have seen in other languages. You have been berating me about it. Why? Is SO just going to erode to a place where the knowledgeable berate those with less knowledge to go read the docs? – dawg Feb 11 '11 at 17:01
  • @drewk: "berating"? I'm puzzled because I'm not able to transfer concepts among languages. It puzzles me and I can't understand the question. I'd like to answer, but I can't understand it because it seems to involve concepts (like "declaration") that I can't apply to Python. I'm trying to help, but I just can't understand the question. – S.Lott Feb 11 '11 at 17:03
  • 6
    **I am very thankful for the help you have given to me and others here.** Comments like `You should, perhaps, review the Python language reference.` and `trivially yes` and `Continuing to demand a Python document that magically matches a document for an utterly different language` and `I'm puzzled how you could claim that [you RTFM] and yet, somehow, not have found this` can come across as condescending, berating and frustrating to someone on the steep part of the learning curve. It takes lots of time and work to to master all this. What is obvious to you might not be to others. – dawg Feb 11 '11 at 17:32
0

I know this question has been answered for quite a while now, but I also had trouble understanding this and would like to demonstrate how I found the answer with a simple example:

def a():
     print globals()
     b()
a()

In the example above, globals would display the location for the function that was defined with the name b if your main executable code defined a function with the name b. If not, the globals would be empty and call to a would result in

NameError: global name 'b' is not defined  

such as in the example of the wolf. What this means is that while function names need to be declared before they are called for them to exist in the namespace of the main executing code, the function that the main executing code calls already have the definitions found in main which is why function calls from functions need not follow a strict order.

MykelXIII
  • 1,085
  • 1
  • 8
  • 16