19.Functions-definition, calling functions,arguments, return value

So far we have only seen the functions which come with Python either in some file (module) or in interpreter itself (built in), but it is also possible for programmer to write their own function(s) and are called User Defined Functions. These functions can then be combined to form a module which can then be used in other programs by importing them.

Types of Functions
Basically, we can divide functions into the following two types:
Built-in functions - Functions that are built into Python.
User-defined functions - Functions defined by the users themselves.

In Python, a function is a group of related statements that performs a specific task.This operation is specified in a function definition.

The following are the two simple reasons to write a function
  • Creating a new function gives you an opportunity to name a group of statements. Functions can simplify  a program by hiding a complex computation behind a single command.
  • Creating a new function can make a program smaller by eliminating repetitive code.
Syntax of Function
def function_name(parameters): 
 """docstring""" 
     statement(s)
     [ return value(s)/expression]

A function definition that consists of the following components.
Keyword def that marks the start of the function header.
A function name to uniquely identify the function. Function naming follows the same rules of writing identifiers in Python.
Parameters (arguments) through which we pass values to a function. They are optional.
A colon (:) to mark the end of the function header.
Optional documentation string (docstring) to describe what the function does.
One or more valid python statements that make up the function body. Statements must have the same indentation level (usually 4 spaces).
An optional return statement to return a value from the function.

Example of a function
def hello(name): 
     """ This function says hello to the person passed in as a parameter """ 
     print("Hello  " , name )

How to call a function in python?

Once we have defined a function, we can call it from another function, program or even the Python prompt. To call a function we simply type the function name with appropriate parameters.
hello('Binu') 
Hello, Binu. 

The above function does not return any value. Following is a function which uses both argument and return value.

def area (radius):      #function header
    '''Calculates area of a circle.                                           

    require an integer or float value to calculate area.
    returns the calculated value to calling function'''  
    a=3.14*(radius**2)
    return a

a=area(5) #function call
print(a)
a=area(2.3)
print(a)
outputs
78.5
16.610599999999998

Flow of execution
Execution always begins at the first statement of the program. Statements are executed one at a time, in order from top to bottom. Function definitions do not alter the flow of execution of the program, but remember that statements inside the function are not executed until the function is called. Although it is not common, you can define one function inside another.In this case, the inner definition isn’t executed until the outer function is called.
Function calls are like a detour in the flow of execution. Instead of going to the next statement, the flow jumps to the first line of the called function, executes all the statements there, and then comes back to pick up where it left off. This will happen in the case of nested functions also.
Note: When you read a program, don’t read from top to bottom. Instead, follow the flow of execution.

Docstrings
The first string after the function header is called the docstring and is short for documentation string. It is briefly used to explain what a function does.
Although optional, documentation is a good programming practice.
In the above example, we have a docstring immediately below the function header. We generally use triple quotes so that docstring can extend up to multiple lines. This string is available to us as the __doc__ attribute of the function.
>>>print(area.__doc__) # will print the document string
>>>help(area)                # help command will make use of docstring

The return statement

The return statement is used to exit a function and go back to the place from where it was called.It is used to return values to the calling program

Syntax of return
return [values/expression_list]

This statement can contain an expression that gets evaluated and the value is returned. If there is no expression in the statement or the return statement itself is not present inside a function, then the function will return the None object.

Pass by Reference vs Value

All mutable parameters (arguments) in the Python language are passed by reference. It means if you change what a parameter refers to within a function, the change also reflects back in the calling function.Immutable object are passed by value. For example 
def f(x):
    x[0]=10

x=[1,2,3]
f(x)
print(x)
this will print [10,2,3]

def f(s):
    s='cek'
s='mec'
f(s)
print(s)

This will print 'mec'

• Changes to string, variable, and tuple arguments of a function within the function do not affect their values in the calling program.
• Changes to values of elements in list and array arguments of a function within the function are reflected in the values of the same list and array elements in the calling function. 

The point is that simple numerics, strings and tuples are immutable while lists and arrays are mutable. Because immutable objects can’t be changed, changing them within a function creates new objects with the same name inside of the function, but the old immutable objects that were used as arguments in the function call remain unchanged in the calling program. On the other hand, if elements of mutable objects like those in lists or arrays are changed, then those elements that are changed inside the function are also changed in the calling program.

Parameters and Arguments
Parameters are the value(s) provided in the parenthesis when we write function header.These are the values required by function to work. radius is a parameter to function area.If there is more than one value required by the function to work on, then, all of them will be listed in parameter list separated by comma.

Arguments are the value(s) provided in function call/invoke statement. List of arguments should be supplied in same way as parameters are listed. Bounding of parameters to arguments is done 1:1, and so there should be same number and type of arguments as mentioned in parameter list.

Function Arguments

You can call a function by using the following types of formal arguments −
Required arguments
Default arguments
Keyword arguments
Variable-length arguments

Required Arguments
Required arguments are the arguments passed to a function in correct positional order. Here, the number of arguments in the function call should match exactly with the function definition.

To call the function hello(s), you definitely need to pass one argument, otherwise it gives a syntax error as follows 
def hello(s):
  print("hello "+ s)
a call to this function without argument will generate error as shown below
hello(s)
Traceback (most recent call last):
  File "C:\Users\binuvp\AppData\Local\Programs\Python\Python38-32\t.py", line 4, in <module>
    hello()
TypeError: hello() missing 1 required positional argument: 's'

the call hello('binu') will print hello binu message

Default  Arguments/Optional parameter values

def hello(name,msg="Good morning!"):
   print("Hello  " + name  + " ,"  +  msg)

hello('Binu')
output
Hello Binu Good morning!

hello('Binu','Good Night')
output
Hello Binu Good Night

In this function, the parameter name does not have a default value and is required (mandatory) during a call.
On the other hand, the parameter msg has a default value of "Good morning!". So, it is optional during a call. If a value is provided, it will overwrite the default value.

Any number of arguments in a function can have a default value. But once we have a default argument, all the arguments to its right must also have default values.

This means to say, non-default arguments cannot follow default arguments. For example, if we had defined the function header above as:
def hello(msg = "Good morning!", name):
We would get an error as:
SyntaxError: non-default argument follows default argument

Python Keyword Arguments

When we call a function with some values, these values get assigned to the arguments according to their position.

For example, in the above function hello(), when we called it as hello("Binu", "How are you?"), the value "Binu" gets assigned to the argument name and similarly "How are you?" to msg.

Python allows functions to be called using keyword arguments. When we call functions in this way, the order (position) of the arguments can be changed. Following calls to the above function are all valid and produce the same result.
# 2 keyword arguments
hello(name = "Binu",msg = "How are you?") 
 # 2 keyword arguments (out of order) 
hello(msg = "How are you?",name = "Binu") 
#1 positional, 1 keyword argument 
hello("Binu", msg = "How are you?")
#this will create error
hello(name="Binu","How are you?")

Python Arbitrary Arguments

Sometimes, we do not know in advance the number of arguments that will be passed into a function. Python allows us to handle this kind of situation through function calls with an arbitrary number of arguments.

In the function definition, we use an asterisk (*) before the parameter name to denote this kind of argument. Here is an example.
def hello(*names): 
     """This function greets all the person in the names tuple.""" 
     # names is a tuple with arguments 
     for name in names:
         print("Hello", name) 

hello("Binu", "Biju", "Biji", "Bini")

Output
Hello Binu, Biju, Biji, Bini

The following function can add any number of values passed as arguments
def add(*x):
  sum=0
  for i in x:
    sum=sum+i
  print(sum)

add(4,5,6,7,8)
output:
30

Here, we have called the function with multiple arguments. These arguments get wrapped up into a tuple before being passed into the function. Inside the function, we use a for loop to retrieve all the arguments back.

Return Multiple values from  a Function

In Python, you can indeed return multiple values from a function. Let’s explore various ways to achieve this:
Using Tuple:
A tuple is a comma-separated sequence of items enclosed in parentheses.
To return multiple values, simply separate them with a comma and return them as a tuple.
Example:
def divide(x, y): 
     quotient = x // y 
     remainder = x % y 
     return quotient, remainder 

q, r = divide(22, 7) 
print("Quotient:", q) 
print("Remainder:", r)

Output:
Quotient: 3 
Remainder: 1

Using List:
A list is an array-like collection of items enclosed in square brackets.
Unlike tuples, lists are mutable (can be modified).
Example:
def get_info(): 
     name = "Alice" 
     age = 30 
     return [name, age] 
info_list = get_info() 
print("Name:", info_list[0]) 
print("Age:", info_list[1])

Output:
Name: Alice 
Age: 30

Using Dictionary:
A dictionary is similar to a hash or map in other languages.
It associates keys with values.
Example:
def get_data(): 
     data = {} 
     data["city"] = "New York" 
     data["population"] = 8_500_000 
     return data 

city_data = get_data() 
print("City:", city_data["city"]) 
print("Population:", city_data["population"])

Output:
City: New York 
Population: 8500000

Using ‘yield’ (Generator Function):
A generator function uses the yield keyword to produce a sequence of values one at a time.
Example:
def get_values(): 
     yield 42 
     yield "hello" 
     yield [1, 2, 3] 

result = get_values() 
print(next(result)) # Should print 42
for i in result: # will print all values
  print(i)

Python Main Function

Main function is like the entry point of a program. However, Python interpreter runs the code right from the first line. The execution of the code starts from the starting line and goes line by line. It does not matter where the main function is present or it is present or not.

Since there is no main() function in Python, when the command to run a Python program is given to the interpreter, the code that is at level 0 indentation is to be executed. However, before doing that, it will define a few special variables. __name__ is one such special variable. If the source file is executed as the main program, the interpreter sets the __name__ variable to have a value __main__. If this file is being imported from another module, __name__ will be set to the module’s name.__name__ is a built-in variable which evaluates to the name of the current module.

Defining a main Function
In scripts that include the definitions of several cooperating functions, it is often useful to define a special function named main that serves as the entry point for the script. This function usually expects no arguments and returns no value. Its purpose might be to take inputs, process them by calling other functions, and print the results. The definition of the main function and the other function definitions need appear in no particular order in the script, as long as main is called at the very end of the script. 

The next example shows a complete script that is organized in the manner just described. The main function prompts the user for a number, calls the square function to compute its square, and prints the result. You can define the main and the square functions in any order. When Python loads this module, the code for both function definitions is loaded and compiled, but not executed. Note that main is then called within an if statement as the last step in the script. This has the effect of transferring control to the first instruction in the main function’s definition. When square is called from main, control is transferred from main to the first instruction in square. When a function completes execution, control returns to the next instruction in the caller’s code.
def main():
    """The main function for this script."""
    number = float(input("Enter a number: "))
    result = square(number)
    print("The square of", number, "is", result)
def square(x):
    """Returns the square of x."""
    return x * x
    # The entry point for program execution
if __name__ == "__main__":
main()

Like all scripts, the preceding script can be run from IDLE, run from a terminal command prompt, or imported as a module. When the script is imported as a module, the value of the module variable __name__ will be the name of the module, "computeSquare". In that case, the main function is not called, but the script’s functions become available to be called by other code. When the script is launched from IDLE or a terminal prompt, the value of the module variable __name __ will be "__main__". In that case, the main function is called and the script runs as a standalone program. This mechanism aids in testing, as the script can be run repeatedly in the shell by calling main(), rather than reloading it from the editor’s window.

Example: Let’s consider there are two Files(File1.py and File2.py). File1 is as follow.

# File1.py

print("File1 __name__ = %s" %__name__)

if __name__ == "__main__":
    print("File1 is being run directly")
else:
    print("File1 is being imported")


Output:
File1 __name__ = __main__
File1 is being run directly


Now, when the File1.py is imported into File2.py, the value of __name__ changes.

# File2.py

import File1
print("File2 __name__ = %s" %__name__)
if __name__ == "__main__":
    print("File2 is being run directly")
else:
    print("File2 is being imported")

Output:
File1 __name__ = File1 
File1 is being imported 
File2 __name__ = __main__ 
File2 is being run directly

As seen above, when File1.py is run directly, the interpreter sets the __name__ variable as __main__ and when it is run through File2.py by importing, the __name__ variable is set as the name of the python script, i.e. File1. Thus, it can be said that if __name__ == “__main__” is the part of the program that runs when the script is run from the command line using a command like python File1.py.

Comments

Popular posts from this blog

Python For Machine Learning - CST 283 - KTU Minor Notes- Dr Binu V P

46.Classes and Objects in Python- Accessors and mutators

KTU Python for machine learning Sample Question Paper and Answer Key Dec 2020