CodingBison

Python functions (like functions in many other programming languages) offer important key advantages. First, functions promote code-reuse. Second, functions allow programmers to develop modular code (modular codes are easier to maintain and extend). Third, functions promote consistency in behavior. When different callers invoke a common function, then they all run the same code and thus, see the same behavior.

Python functions belong to the category of objects. Since functions are objects, we can assign functions to variables or even pass them as parameters to other functions.

Before proceeding further, let us understand two key properties of functions: arguments and return values.

Arguments are a set of variables that a caller passes to a function. A function can take any number of arguments (including zero) and uses these arguments as an input to its logic. If the caller passes extra arguments than what is defined in the function, then Python will throw a TypeError. However, the caller can pass less number of arguments, as long as the function definition defaults those arguments to None in the function definition.

Return value is a value that the function passes back to the caller. This value is, typically, based on the argument input and function uses these arguments to compute the return value. However, it is not necessary for a function to return any value!

A function definition has several syntax elements. First, we need to provide the "def" keyword to identify that the object is a function. Next, we need to provide the name of the function (e.g. "animalSays"); Third, we can provide zero or more arguments. Fourth, we need to indent the body of the function as the body of the function forms a Python block. Last, a function can also return a value.

Let us see an example to understand these function elements. This example defines a function ("animalSays") that returns the animal sound for a given animal. It takes one argument (argAnimal) and does a lookup in a dictionary and returns the value pertaining to the animal. After we invoke the function, the returned value from the function is automatically assigned to the variable retVal.

 #This is a simple function. 
 def animalSays(argAnimal):
     dictAnimals = {"tiger": "roars", "wolf": "howls", "bird": "tweets"}

     if (dictAnimals.has_key(argAnimal)):
         return dictAnimals[argAnimal]
     else:
         return "says something that I don't know!" 

 print(type(animalSays)) 

 #Invoke the function.
 retVal = animalSays("tiger")
 print("A tiger " + retVal)

 #Invoke the function again.
 print("A Loch Ness Monster " + animalSays("Loch Ness Monster"))

We can run the above example by storing it in a file (let us say "function-basic.py") and pass it as argument to python3 -- python3 is the Python 3.x version. Also, the output shows that the typeof operator returns "function" for functions.

 [user@codingbison$ python3 function-basic.py 
 <type 'function'>
 A tiger roars
 A Loch Ness Monster says something that I don't know!
 [user@codingbison$ 

We can see that unlike some other languages (such as C), we do not have to declare (provide the prototype of) the function first -- we can define it (which means provide the entire body of the function) and use it right away. In addition, we do not have to specify the return type for a function.

Since Python functions are objects, we can assign them to variables. Once we assign a function to a variable, we can simply use the variable name to invoke the function. Let us rewrite the earlier example to show this behavior; when we run the following example, the output is same as before.

 #This is a simple function. 
 def animalSays(argAnimal):
     dictAnimals = {"tiger": "roars", "wolf": "howls", "bird": "tweets"}

     if (dictAnimals.has_key(argAnimal)):
         return dictAnimals[argAnimal]
     else:
         return "says something that I don't know!" 

 #Assign the function name to a variable.
 varFuncAnimalSays = animalSays

 print(type(varFuncAnimalSays)) 

 #Invoke the function.
 retVal = varFuncAnimalSays("tiger")
 print("A tiger " + retVal)

 #Invoke the function again.
 print("A Loch Ness Monster " + varFuncAnimalSays("Loch Ness Monster"))

A Python function does not necessarily has to return anything. Here is yet another implementation of the animalSays() function, where we move the task of returning the string and printing it from the main program to the animalSays() function itself. And, therefore, this function does not need to return anything; the output is same as before.

 #This is a simple function. 
 def animalSays(argAnimal):
     dictAnimals = {"tiger": "roars", "wolf": "howls", "bird": "tweets"}

     strOutput = "A " + argAnimal + " " 
     if (dictAnimals.has_key(argAnimal)):
         strOutput += dictAnimals[argAnimal]
     else:
         strOutput += "says something that I don't know!" 

     print(strOutput)

 #Invoke the function.
 animalSays("tiger")

 #Invoke the function again.
 animalSays("Loch Ness Monster")

Recursive Functions

Functions are fairly versatile and can even call themselves! Such functions are known as recursive functions.

Recursive functions can be called for cases where the problem space can be made smaller at each step. As one example, let us say we start with a series of data. With recursive function, we can start with the first element of the series, and then call the same function to process the next element in the series. We can do so till we reach the end of the series. At each call, the remaining series is passed as the argument to the next call of the same function.

The below-provided example uses a recursive function to compute factorial of a number. The factorial of a number, N is (N * (N-1) * (N-2) *..... * 3 * 2 * 1). Thus, factorial of 4 would be 4 * 3 * 2 * 1 = 24. In this example, the function getFactorial() calls itself recursively to compute factorial for 4 and

 def getFactorial(num):
     factorial = 1 

     print("Computing factorial for " + str(num))
     if (num == 1): 
         return factorial

     factorial = num * getFactorial(num-1);
     return factorial

 retValue = getFactorial(4) 
 print("The factorial of 4 is " + str(retValue)) 

The output (provided below) shows how the function calls itself for all the integers starting from 4 to 1.

 [user@codingbison]$ python3 function_recursive.py 
 Computing factorial for 4
 Computing factorial for 3
 Computing factorial for 2
 Computing factorial for 1
 The factorial of 4 is 24
 [user@codingbison]$ 




comments powered by Disqus