we know that we have to declare a function before we use it
It sounds like you're coming from a language in the C family. These languages are different in two ways.
First, Python doesn't "declare" anything. That makes sense in languages like C, where variables are typed memory locations that values get stored in. But in Python, values have their own independent types and locations, and variables are just names for those values, so there is nothing to declare.
Now, Python requires you to define a function before you use it, just like C.
But only C also requires you to define, or at least declare, a function before you compile a function whose body uses it. The difference is the same as above—C needs the function to be declared, to get the types, the pointer to the function's actual code, etc.; in Python, the function is just a name for the function-object value. To compile a function, all it needs to know is where to look up the names. And that's easy: it compiles the function so that, at runtime, it will look up the name in the module globals. Since no other information is needed, there's nothing to declare.
For example, in C, this is legal:
void foo() {}
void bar() { foo(); }
And so is this:
void foo();
void bar() { foo(); }
void foo() {}
But this is not:
void bar() { foo(); }
void foo();
In Python, because there are no declarations, the second and third are identical, and therefore both perfectly valid:
def bar():
foo()
def foo():
pass