77

I use Python CGI. I cannot call a function before it is defined.

In Oracle PL/SQL there was this trick of "forward declaration": naming all the functions on top so the order of defining doesn't matter.

Is there such a trick in Python as well?

example:

def do_something(ds_parameter):
    helper_function(ds_parameter)
    ....

def helper_function(hf_parameter):
    ....

def main():
    do_something(my_value)

main()

David is right, my example is wrong. What about:

<start of cgi-script>

def do_something(ds_parameter):
    helper_function(ds_parameter) 
    .... 

def print_something(): 
    do_something(my_value) 

print_something() 

def helper_function(hf_parameter): 
    .... 

def main()
    ....

main()

Can I "forward declare" the functions at the top of the script?

meetar
  • 7,443
  • 8
  • 42
  • 73
user37986
  • 1,107
  • 2
  • 11
  • 12
  • Since the example code will work, and is order-independent, I don't get the question. – S.Lott Apr 16 '09 at 22:29
  • Regarding the "David is right" edit: Again, why would you need to execute `print_something()` before defining the remaining functions? There's still no need to "forward declare". Just finish defining your functions before calling any of them. – mikenerone Mar 30 '22 at 22:54

7 Answers7

95

All functions must be defined before any are used.

However, the functions can be defined in any order, as long as all are defined before any executable code uses a function.

You don't need "forward declaration" because all declarations are completely independent of each other. As long as all declarations come before all executable code.

Are you having a problem? If so, please post the code that doesn't work.


In your example, print_something() is out of place.

The rule: All functions must be defined before any code that does real work

Therefore, put all the statements that do work last.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • I think that the default parameters of a function declaration do require a forward declaration, e.g. `def f(x=g()): .. def g(): .. ` won't compile even if it is not used at the time of the declaration. – mnish Aug 03 '17 at 02:13
  • 6
    @mnish True, which nicely illustrates that the **default parameters are evaluated at compile time**, which is often not what is intended. Use `f(x=None): ...` and `if x is None: x = g()` instead. – j08lue Aug 08 '17 at 08:55
46

An even better illustration of your point would be:

def main():
    print_something() 
    ....

def do_something(ds_parameter):
    helper_function(ds_parameter) 
    .... 

def print_something(): 
    do_something(my_value) 


def helper_function(hf_parameter): 
    .... 


main()

In other words, you can keep your definition of main() at the top, for editing convenience -- avoiding frequent scrolling, if most of the time is spent editing main.

Brad Koch
  • 19,267
  • 19
  • 110
  • 137
Stan Vernon
  • 469
  • 4
  • 2
  • 4
    This is why it makes so much sense to separate declarations and executed code by the common `if __name__ == "__main__":` barrier. – j08lue Aug 08 '17 at 08:57
  • I am confused about the usage. The code fails if I make them to be inner functions inside `main()`. – Simon Z. Sep 06 '20 at 13:24
  • @SimonZ. Functions defined inside `main` can only be seen within `main`, you can't use them at a global scope. – Mark Ransom Jun 07 '21 at 15:23
5

Assuming you have some code snippet that calls your function main after it's been defined, then your example works as written. Because of how Python is interpreted, any functions that are called by the body of do_something do not need to be defined when the do_something function is defined.

The steps that Python will take while executing your code are as follows.

  1. Define the function do_something.
  2. Define the function helper_function.
  3. Define the function main.
  4. (Given my assumption above) Call main.
  5. From main, call do_something.
  6. From do_something, call helper_function.

The only time that Python cares that helper_function exists is when it gets to step six. You should be able to verify that Python makes it all the way to step six before raising an error when it tries to find helper_function so that it can call it.

David Locke
  • 17,926
  • 9
  • 33
  • 53
  • 1
    Worth noting that this is also true of variables (since a function is really just a variable that happens to support being called). – DimeCadmium Apr 11 '18 at 01:16
3

I've never come across a case where "forward-function-definition" is necessary.. Can you not simply move print_something() to inside your main function..?

def do_something(ds_parameter):
    helper_function(ds_parameter) 
    .... 

def print_something(): 
    do_something(my_value) 


def helper_function(hf_parameter): 
    .... 

def main()
    print_something() 
    ....

main()

Python doesn't care that helper_function() is defined after it's use on line 3 (in the do_something function)

I recommend using something like WinPDB and stepping through your code. It shows nicely how Python's parser/executor(?) works

dbr
  • 165,801
  • 69
  • 278
  • 343
  • "forward-function-definitions" are in C and C++ quite normal and are very often used. They make the code clean and elegant. I'm surprised as well, that python doesn't offer the same – Dave Apr 24 '22 at 06:14
2
def funB(d,c):
   return funA(d,c)

print funB(2,3)

def funA(x,y):
    return x+y

The above code will return Error. But, the following code is fine ...

 def funB(d,c):
     return funA(d,c)

 def funA(x,y):
     return x+y

 print funB(2,3)

So, even though you must definitely define the function before any real work is done, it is possible to get away if you don't use the function explicitly. I think this is somewhat similar to prototyping in other languages.. .

nyan314sn
  • 1,766
  • 3
  • 17
  • 29
2

For all the people, who despite bad practice want a workaround...
I had a similar problem and solved it like this:

 import Configurations as this
 '''Configurations.py'''
 if __name__ == '__main__':
   this.conf01()

 '''Test conf'''
 def conf01():
   print ("working")

So I can change my targeted configuration at the top of the file. The trick is to import the file into itself.

luke8800gts
  • 398
  • 3
  • 7
0

Use multiprocessing module:

from multiprocessing import Process

p1 = Process(target=function_name, args=(arg1, arg2,))
p1.start()
Neeraj Bansal
  • 2,580
  • 16
  • 8