Nikolay Dudaev
Nikolay Dudaev

Reputation: 392

Difference in declaring a function in Python and C

I am reading and learning now Python and C at the same time. (Don't ask me why, it is a lot of fun! :-)) I use "Learning Python" by Mark Lutz. Here is what he writes about functions in Python:

Unlike in compiled languages such as C, Python functions do not need to be fully defined before the program runs. More generally, defs are not evaluated until they are reached and run, and the code inside defs is not evaluated until the functions are later called.

I do not quite get it as in my second book K.N.King says that you CAN declare a function first and create a definition later.

English is not my native language so what I am missing here?

I can make only one guess, that it is somehow related to program runtime. In C the compiler runs through the program and finds the function declaration. Even if it is not defined, compiler goes on and finds function definition later. Function declaration in C helps to avoid problems with return-type of a function (as it is int by default). On the other hand in Python function is not evaluated until it is reached during runtime. And when it is reached, it does not evaluate the body of a function until there is a function call. But this guess does not explain a quote above.

What is then Mr.Lutz is talking about? I am confused a bit...

Upvotes: 3

Views: 1229

Answers (5)

abhay patil
abhay patil

Reputation: 89

Sample python:

foo()
def foo():
    #some code

That errors as the python interpreter didn't find any function before it is called. But:

def foo():
    bar() #just declared and not called yet

def bar():
    print("42")
foo() #now it is called and bar() is also got interpreted 

This will print 42 without any error, as the interpreter has interpreted and executed the previous lines until foo() was called in the end.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1124110

Python functions are 'executed' when the source code comes to them:

def foo():
    return bar

def bar():
    return 'spam'

Here foo depends on bar, but it doesn't matter that the bar function definition is not executed until after foo has been declared. Only when you then call foo() does the name bar need to exist.

In C however, you cannot do the above without an additional prototype declaration:

char * bar(void);

char * foo(void) {
    return bar();
}

char * bar(void) {
    return "spam";
}

So yes, you can postpone the full declaration of bar but the compiler demands that you still declare the function signature up front.

So Python doesn't care whether or not bar is defined until runtime, C requires functions to be declared at compile time.

Upvotes: 5

skyking
skyking

Reputation: 14400

In python you have no such thing as forward declarations. Symbols referenced in a function (code) does not get looked up until the function is called. That's why you don't need to define the function in order. For example

def foo():
    return bar()

def bar():
    return 42

foo()

First of all this is all compiled, but I'll skip those details. The code when executed will first define a function named foo with the body/code that says "find something called bar and call it and then return the return value". The similar happens for bar. And last at foo() the interpreter runs the code saying "find something named foo and call it". It this point foo is defined so it's called and it's body is executed, but that says "find something called bar and call it", but at this point we already has passed the point where bar is defined.

Now let's look at C:

int foo() {
    return bar();
}

int bar() {
    return 42;
}

now we have some slight problem here because the name lookup have to be done at build time, that's not a big problem here, but keep in mind that the C compiler processes the source sequentially so it will not look ahead. So when compiling foo it sees that you're trying to call something called bar which the compiler has no idea what it is - so it assumes that you've used bar correctly and figures out that it's a function taking no arguments and returns an int (no arguments passed, and by default it assumes it returns int). Then when you reach the definition of bar lucky you that the assumtion was correct (because the compiler has already made up his mind and generated code in foo assuming that - otherwise you would get odd behaviour). Last (when linking) it will resolve all symbols (no matter which order you put the declarations) and the placeholder for the name will just be a reference to what the name refers to. At this point the implementation could drop the names as they have no purpose for the program any more (but may select to keep them as it may help if you need to debug the program).

Now if you would like to be a little more secure you would have forward declarated bar so that the compiler can check that you actually calls it with arguments of correct type (and interpret the return value as the correct type). You would then have:

int bar(void);

int foo(void) {
    return bar();
}

int bar(void) {
    return 42;
} 

If you did program in C++ this later way of doing it would be mandatory since C++ doesn't allow for guessing the parameter types, but also you're recommended to do so in C too (there's compiler warnings that warns for in the first C example that the compiler have to guess what bar is).

Upvotes: 4

BobRun
BobRun

Reputation: 754

In C you can compile without declaring, the compiler assumes the function is int, if that's the case your program compiles and runs. If your function or functions are another type you'll get problems and you'll have to declare. It is often quicker to not declare and generate your declarations from your code to an h file and include where needed. You can leave it to a program to write this part of your program. Just like you can leave the indent, write a big mess and let indent do it for you.

Upvotes: 0

Justin Lessard
Justin Lessard

Reputation: 11941

In the following example, text_func isn't defined when we first start the execution. In python, function are defined at runtime, when we execute the def line.

print ('Entry point. No custom functions/methods are defined at this point')

print ('Defining test_func')
# We defined a function here.
# The function is defined at runtime since python when we run this line
def test_func():
    # Obviously, the body of the function is executed only when we call the function.
    # Not when we define it
    print ('evaluating test_func now')


print ('test_func is now defined.')

test_func()

Upvotes: 0

Related Questions