Functions

# A function is a block of code consisting of one or more Python statements which are invoked together as a sequence of instructions when the function is called.

If a function is defined with parameters then you have to invoke such a function with necessary arguments.

We have already called several functions in this book. E.g.;

print("hello")
input("please type in anything")

Both these functions are taking one argument each; 'hello' and 'please type in anything' respectively in these examples.

These functions were already available in Python and we used them. Now we will create our own function a.k.a. user defined functions.

User Defined Function

Here is an example of a user defined function that generates a list of even numbers up to some given number as input. It is named, generate_even_numbers and the number upto which it has to generate the even numbers is defined as a parameter with the name 'limit'. Here is the full implementation of the function definition:


# definition of the function with one parameter - limit
def generate_even_numbers(limit):  
    even_number_list = []  
    for i in range(2, limit, 2): 
        even_number_list.append(i) 
    return even_number_list

You define a function by using the def keyword and the name of the function and a colon, followed by the full implementation of the function. By now you are familiar with the rest of the statements after the colon. The only other keyword that you have not seen so far is the return

Once this function is defined, this function can be called as shown in the code below:

generate_even_numbers(10)

The value '10' that is passed is here is the 'argument' for the parameter 'limit' that is defined in the function.

return keyword: You use the return keyword to pass something from the function back to the calling statement. You will see it in action below.

The generate_even_numbers function, when invoked with argument 10, creates a list of even numbers below 10 and returns that list as there is a return statement. The return value of this function is shown below:

[0, 2, 4, 6, 8]

The full code for invoking this function is shown below:


even_numbers = generate_even_numbers(10)
print(even_numbers)

Since a list of even numbers is returned, 'even_numbers' variable will have a reference to this list object that is returned from the function. Note however, that you named that list variable 'even_number_list' inside the function. However that variable is not accessible from outside of the function code block and the only way the values can be accessed is by returning that object from the function. And you have to have another variable, in our case, 'even_numbers', which receives the reference to this returned object.

When the program of execution hits a return statement, the program exits the function call and any other statements after the return is not executed.

You can send different values for the argument in this function while invoking and accordingly your results will be different. Once a function is defined, you can invoke that function any number of times with different variables and each time it returns a list based on the input number.

This function is defined to receive one argument. If you do not send the required argument within the parenthesis, then you get a TypeError

TypeError: generate_even_numbers() missing 1 required positional argument: 'limit'

Function with no return

If a function does not return anything, then the variable that tries to receive the returned value will have a None value. Here is an example of such an invocation:

def displayGreetings(name):
    print("Greetings!", name + ",",  "hope you are having a good day")

a = displayGreetings("Foo")
type(a)

Output:

Greetings! Foo Hope you are having a good day
NoneType

While the above was a user defined function, you have been using such functions which return nothing. Here is an example of built-in function 'print' which return nothing:

a = print('Z')
print(a)

Output:

Z
None

Documentation

You can add documentation to a function so that others can understand how to use the function, by adding comment lines with three single or double quotes. Here is the same modified function with documentation


def generate_even_numbers(limit):  
    '''
    This method generates even numbers from 0 to the value 
    passed in the 'limit' parameter, excluding the 'limit' value
    '''
    even_number_list = []  
    for i in range(2, limit, 2): 
        even_number_list.append(i) 
    return even_number_list

You notice that this function has documentations described between three single quotes. This comment line will be displayed when the user invokes 'help', another built-in function, function by sending in the name of the function as an argument.

Here is how it is invoked:

help(generate_even_numbers)

Output:

Help on function generateevennumbers in module __main:
generate_even_numbers(limit)
This method generates even numbers from 0 to the value passed in the 'limit' parameter, excluding the 'limit' value

Difference between argument and parameter

Parameters are variable names that are defined in a function. Arguments are the values that are sent to the variable defined in the function when the function is invoked.

Function Definitions With Default Values

Sometimes you may have to define a function with one or more default argument values. In such cases all the default arguments can be defined after all the non-default arguments are defined. Here is an example;

def dosomething(state, county, country="US"):
    print(country, state, county)

dosomething('MI', 'Wayne')
dosomething('MI', 'Wayne', "United States of America")

output:

US MI Wayne United States of America MI Wayne

With the above function definition, you can invoke the function with or without a value for 'country'. If you pass country value then the passed in value would be considered. If it is missing then the default value defined in the function definition will be used.

Function Definitions with Variable Arguments and Keyword Arguments

Occasionally you may require a function which can accept variable arguments. In such cases you can use the * (asterisk) and/or ** (double asterisk) against the parameter names to receive many comma separated arguments and/or keyword arguments respectively. Here is an example;

def dosomething(*args, **kwargs):
    print(kwargs)  # receives a dictionary of keyword arguments
    print(args)   # receives a tuple of all arguments.

dosomething(1, 2, 3, country='US', county='Wayne')

output:

{'country': 'US', 'county': 'Wayne'} (1, 2, 3)

Referencing variable from outer scope inside a function

Supposing you want to reference a variable outside of the function, you can do so only by using global keyword. Here is an example

x = 10
def dosomething():
    x += 100
    print(x)

dosomething()

Output:

UnboundLocalError: local variable 'x' referenced before assignment

The above reference of the outer variable throws an error. You can fix this by assigning the global keyword for the variable x. Here is the code:


x = 10
def dosomething():
  global x
  x = x + 100
  print(x)

dosomething()

Output:
110

Note: All variables that are declared inside a function are considered local by default unless 'global' keyword is used.

However you can reference an outer variable inside the function. Here is the example to illustrate that:


x = 10
def dosomething():
  print(x)

dosomething()

Output:

10

Understanding variable scope in Python

By default all variables declared in a python file (the .py file which becomes a module if used by other programs) is visible to conditional code blocks like if, while, functions etc.. inside that file.

However the variables in a file are not automatically global by referencing by its name only across all other modules, unlike in languages such as JavaScript. Variables which are in one module can be accessed in other modules by way of importing that module and prepending the variable name with module name/namespace.

* for Unpacking Collections

Asterisk (*) performs argument unpacking. This is used with an enclosing function. Here is an example;


def multiply(a, b):
    return a * b

print(multiply(*[2, 3]))

output:

6

Note however that, you cannot use asterisk by itself without an enclosing function. Although the example shows a list, you can replace the list with any collection object like tuple, set etc..

** for Unpacking Dictionary

You can use double asterisk (**) to unpack a dictionary into name, value pairs. Here too it should be used as an argument to a function. Here is an example;

def dosomething(country,state,county):
    print(country, state, county)

my_place = {'state':'Michigan', 
                'county':'Wayne', 'country':'United States',}
dosomething(**my_place)

output:

United States Michigan Wayne

 

Highlights

  • def keyword is used to define a function
  • function should be defined first before it is invoked.
  • A function is a block of code which can be called by the same or different program
  • A function can take 0 or more arguments as long as the respective parameters are defined in the function definition.
  • You can set default values to certain arguments by defining the default argument values after all the non-default arguments are defined.
  • You can also send variable length of arguments to a function by using an asterisk before the argument name.
  • You can also send a variable length of keyword arguments by using double asterisk before the keyword arguments name.
  • Multiple arguments are separated by a comma in both the definition and invocation. The order of arguments is important when you call the function- you should maintain the same order as the definition, while passing the values to the arguments unless when the function is defined for arbitrary arguments and/or keyword arguments list.
  • A return statement, if present will return any object back from the function to the calling program.
  • Function definition should come before the function is called otherwise you will get NameError

 

Naming convention

  • It is a recommended practice to name all variables with a noun and all function names should be a verb. The reasoning behind this is, a variable holds a value and inherently does not do anything else with it so it should be a noun. A function on the other had is doing something on the arguments passed. It is taking some action on it and hence should be named with a verb.

Anonymous functions a.k.a. Lambda functions

In python you can create functions without the def keyword and a name. These are called Lambda functions. Lambda functions can be created when the function has only one expression in its body. Let us take an example:


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

In the above function definition, there is only one expression x+y which is returned. So this is a good candidate for defining it as a Lambda function instead. Here is how it is defined as a Lambda:


(lambda x,y : x+y)(5, 10)

Output:
15

In this the Lambda function is taking x and y as arguments and the expression x+y after colon, is the body of the lambda function. As you can see lambda function has no name and it gets called when you pass arguments (5,10) to it through a pair of parenthesis.

results matching ""

    No results matching ""