6 min readJun 24, 2021


What is a function in Python?

In Python, a function is a group of related statements that performs a specific task.

Functions help break our program into smaller and modular chunks. As our program grows larger and larger, functions make it more organized and manageable.

Furthermore, it avoids repetition and makes the code reusable.

Syntax of Function

def function_name(parameters):

Above shown is a function definition that consists of the following components.

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

How Function works in Python?


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. Unless you can remember what you had for dinner last week, always document your code.

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.

For example:

Try running the following into the Python shell to see the output.

>>> print(greet.__doc__)    This function greets to
the person passed in as
a parameter

The return statement

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

Syntax of return

return [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.

For example:

>>> print(greet("May"))
Hello, May. Good morning!

Here, None is the returned value since greet() directly prints the name and no return statement is used.

Example of return

def absolute_value(num):
"""This function returns the absolute
value of the entered number"""
if num >= 0:
return num
return -num



What are modules in Python?

Modules refer to a file containing Python statements and definitions.

A file containing Python code, for example:, is called a module, and its module name would be example.

We use modules to break down large programs into small manageable and organized files. Furthermore, modules provide reusability of code.

We can define our most used functions in a module and import it, instead of copying their definitions into different programs.

Let us create a module. Type the following and save it as

# Python Module exampledef add(a, b):
"""This program adds two
numbers and return the result"""
result = a + b
return result

Here, a function add() inside a module named example. The function takes in two numbers and returns their sum.

How to import modules in Python?

We can import the definitions inside a module to another module or the interactive interpreter in Python.

We use the import keyword to do this. To import our previously defined module example, we type the following in the Python prompt.

>>> import example

This does not import the names of the functions defined in example directly in the current symbol table. It only imports the module name example there.

Using the module name we can access the function using the dot . operator. For example:

>>> example.add(4,5.5)

List Comprehension

List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list.


Based on a list of fruits, you want a new list, containing only the fruits with the letter “a” in the name.

Without list comprehension you will have to write a for statement with a conditional test inside:

fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
newlist = []

for x in fruits:
if "a" in x:


With list comprehension you can do all that with only one line of code:

fruits = ["apple", "banana", "cherry", "kiwi", "mango"]

newlist = [x for x in fruits if "a" in x]


The Syntax

newlist = [expression for item in iterable if condition == True]

The return value is a new list, leaving the old list unchanged.


The condition is like a filter that only accepts the items that valuate to True.

Only accept items that are not "apple":newlist = [x for x in fruits if x != "apple"]

The condition if x != “apple” will return True for all elements other than "apple", making the new list contain all fruits except "apple".

The condition is optional and can be omitted:

With no if statement:newlist = [x for x in fruits]

Python Iterators, generators

Iterators are containers for objects so that you can loop over the objects. In other words, you can run the “for” loop over the object. There are many iterators in the Python standard library. For example, list is an iterator and you can run a for loop over a list.

__iter__ returns the iterator object itself. This is used in for and in statements.

__next__ method returns the next value from the iterator. If there is no more items to return then it should raise StopIteration exception.

class Counter(object):
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
'Returns itself as an iterator object'
return self
def __next__(self):
'Returns the next value till current is lower than high'
if self.current > self.high:
raise StopIteration
self.current += 1
return self.current - 1

Now we can use this iterator in our code.

>>> c = Counter(5,10)
>>> for i in c:
... print(i, end=' ')
5 6 7 8 9 10

Remember that an iterator object can be used only once. It means after it raises StopIteration once, it will keep raising the same exception.

>>> c = Counter(5,6)
>>> next(c)
>>> next(c)
>>> next(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in next
>>> next(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in next

Using the iterator in for loop example we saw, the following example tries to show the code behind the scenes.

>>> iterator = iter(c)
>>> while True:
... try:
... x = iterator.__next__()
... print(x, end=' ')
... except StopIteration as e:
... break
5 6 7 8 9 10


In this section we learn about Python generators. It is an easier way to create iterators using a keyword yield from a function.

>>> def my_generator():
... print("Inside my generator")
... yield 'a'
... yield 'b'
... yield 'c'
>>> my_generator()
<generator object my_generator at 0x7fbcfa0a6aa0>

In the above example we create a simple generator using the yield statements. We can use it in a for loop just like we use any other iterators.

>>> for char in my_generator():
... print(char)
Inside my generator

Generator expressions

In this section we will learn about generator expressions which is a high performance, memory efficient generalization of list comprehensions and generators.

For example we will try to sum the squares of all numbers from 1 to 9.

>>> sum([x*x for x in range(1,10)])

The example actually first creates a list of the square values in memory and then it iterates over it and finally after sum it frees the memory. You can understand the memory usage in case of a big list.

We can save memory usage by using a generator expression.

sum(x*x for x in range(1,10))

The syntax of generator expression says that always needs to be directly inside a set of parentheses and cannot have a comma on either side. Which basically means both the examples below are valid generator expression usage example.

>>> sum(x*x for x in range(1,10))
>>> g = (x*x for x in range(1,10))
>>> g
<generator object <genexpr> at 0x7fc559516b90>