Understanding Function, Module & Class In Python

This is the 6th post in a series of learning the Python programming language.


A function is a block of code that performs a specific task. Functions are defined using the “def” keyword, followed by the function name and a set of parentheses that may contain parameters. The code block within the function is indented and starts with a colon. Functions can take input parameters and return output.

Here’s an example of a simple function called “greet”:

def greet(name):
print("Hello, " + name)


This function takes one parameter called “name” and prints “Hello, name” to the console. When the function is called with the argument “John”, the output will be “Hello, John”.

Functions can also return values using the “return” statement. For example, the following function takes two numbers as input and returns their sum:

def add(a, b):
return a + b

result = add(3, 4)

This function takes two parameters, “a” and “b”, adds them together, and returns the result. When the function is called with the arguments 3 and 4, the output will be 7.

Functions can also have default values for their parameters, which are used when a value is not provided when the function is called. For example:

def greet(name, greeting="Hello"):
print(greeting + ", " + name)

greet("John") # prints "Hello, John"
greet("John", "Hi") # prints "Hi, John"

In this example, the function “greet” takes two parameters, “name” and “greeting”, with “greeting” having a default value of “Hello”. When the function is called with only one argument, the default value is used for the second argument.

Functions are first-class citizens

In Python, Functions are first-class citizens, meaning they can be treated like any other data type, such as an integer or string. They can be passed as arguments to other functions, stored in data structures, and so on.

Lambda functions

Additionally, Python has a feature called “lambda functions” which allows you to define a small anonymous function in a single line. They are also known as “anonymous functions” or “lambda expressions”.

add = lambda a, b : a + b
result = add(3,4)

In Python, function arguments can also be passed using special syntax *args and **kwargs which allows a function to accept a variable number of arguments. *args allows a function to accept any number of non-keyword arguments and **kwargs allows a function to accept any number of keyword arguments.

def test_function(arg1, *args, **kwargs):
print(arg1) # 1
print(args) # (2, 3, 4, 5)
print(kwargs) # {'name': 'John', 'age': 25}

test_function(1, 2, 3, 4, 5, name='John', age=25)

Function decorators

In Python, a function decorator is a feature that allows you to modify the behavior of a function, without modifying its code. A function decorator is a function that takes another function as input and returns a new function. The new function, also known as the “decorated” function, typically includes additional functionality before or after the original function is called.

Function decorators are defined using the “@” symbol followed by the decorator function name. Here is an example of a simple decorator function that adds logging functionality to a function:

def my_logger(original_function):
import logging
logging.basicConfig(filename='{}.log'.format(original_function.__name__), level=logging.INFO)

def wrapper(*args, **kwargs):
'Ran with args: {}, and kwargs: {}'.format(args, kwargs))
return original_function(*args, **kwargs)

return wrapper

def display():
print('display function ran')


In this example, the my_logger function is a decorator that takes the display function as input and returns a new function called wrapper. The @my_logger syntax is a shortcut for saying display = my_logger(display). When display is called, it runs the code within the wrapper function, which includes logging the input arguments and the return value of the original `display


A module in Python is a single file that contains Python code. It can define functions, classes, and variables, and can be imported into other Python files or scripts to be used.

To create a module, simply create a new .py file and write your Python code inside it. You can then import the module into other files using the import statement. For example, if you have a module named “”, you can import it into another file using the following code:

import mymodule

Once the module is imported, you can access its functions, classes, and variables using the dot notation. For example, if the module “” defines a function named “myfunction()”, you can call that function using the following code:


You can also use the “from” keyword to import specific elements from a module. For example, you can use the following code to import only the “myfunction()” function from “”:

from mymodule import myfunction

After that, you can use the function directly without prefixing the module name.


You can also use the “as” keyword to give a module or a specific element from a module a different name when importing it. For example, you can use the following code to import “” and give it the name “m”:

import mymodule as m

Once you have imported the module, you can access its elements using the new name.


It’s important to note that when you import a module, Python runs all the code in the module. If you have any code in your module that you only want to run when the module is run directly, you can use the following code at the bottom of your module:

if __name__ == "__main__":
# code to run when the module is run directly

This way when you import the module the code inside this block won’t be executed but when you run the module directly, the code inside the block will be executed.


A class is a blueprint for creating objects (a particular data structure), providing initial values for state (member variables or attributes), and implementations of behavior (member functions or methods).

The class is defined using the “class” keyword, followed by the name of the class. The class definition usually contains a number of class variables and class methods.

A class variable is a variable that is shared by all instances of a class. Class variables are defined within the class but outside of any of the class’s methods.

A class method is a method that is bound to the class and not the instance of the object.

An object is an instance of a class and has its own state and behavior. An object can be created using the class name followed by parentheses.

class Person:
species = "Homo sapiens"

def __init__(self, name, age): = name
self.age = age

def info(self):
return f"{} is {self.age} years old"

p1 = Person("John", 36)
p2 = Person("Amy", 25)


In the above example, species is a class variable that is shared by all instances of the class Personname and age are instance variables, which are unique to each object. info() is a method that is common to all instances of the class Person.

There are different types of methods that can be defined within a class:

  1. Instance method: These are the most common type of method and are bound to a specific instance of the class. They can access and modify the state of the instance, and typically use the “self” parameter to refer to the instance.
  2. Class method: These methods are bound to the class itself, rather than a specific instance. They are defined using the “@classmethod” decorator and use the “cls” parameter to refer to the class. Class methods are often used for factory methods, which create and return new instances of the class.
  3. Static method: These methods are also bound to the class, rather than a specific instance. They are defined using the “@staticmethod” decorator and do not have access to the class or instance state. Static methods are often used for utility functions that don’t need to access any class or instance data.
class MyClass:
x = [1, 2, 3]

def __init__(self, value):
self.value = value

def instance_method(self):
print(f"This is an instance method. Value = {self.value}")

def class_method(cls):
print(f"This is a class method. x = {cls.x}")

def static_method():
print("This is a static method.")

def normal_method():
print("This is a normal method.")
  • instance_method() is an instance method because it takes the self parameter, which refers to the instance of the class. When called on an instance of the class, it can access and modify the instance’s value attribute.
  • class_method() is a class method because it takes the cls parameter, which refers to the class itself. When called on the class, it can access and modify class-level attributes, such as the x attribute.
  • static_method() is a static method because it doesn’t take any special parameters, such as self or cls. It can’t access or modify any instance or class-level attributes, but it can be called on the class or an instance of the class.

You can call these methods on an instance of the class like this:

obj = MyClass(10)
obj.instance_method() # This is an instance method. Value = 10
obj.class_method() # This is a class method. x = [1, 2, 3]
obj.static_method() # This is a static method

You can also call these methods on the class itself:

MyClass.class_method() # This is a class method. x = [1, 2, 3]
MyClass.static_method() # This is a static method

OOPs Concepts

(Object-oriented programming) is a programming paradigm that uses objects and their interactions to design applications and computer programs. The main concepts of OOP are encapsulation, inheritance, and polymorphism.


Encapsulation refers to the practice of hiding internal data and methods from external access and providing a public interface for interacting with the object. This ensures that the internal state of the object is protected from accidental or intentional changes and that the object’s behavior is consistent.

An example of encapsulation in Python is the use of the private and protected access modifiers, which are denoted by a single or double underscore prefix, respectively, on the name of a class member (attributes and methods). These members can only be accessed within the class or its subclasses.

class MyClass:
def __init__(self):
self.__private_var = 0
self._protected_var = 0

def set_private_var(self, value):
self.__private_var = value

def get_private_var(self):
return self.__private_var

def set_protected_var(self, value):
self._protected_var = value

def get_protected_var(self):
return self._protected_var

In the above example, __private_var and _protected_var can only be accessed within the class ‘MyClass’, and it’s not possible to access it directly from the object.


Inheritance is the ability to create new classes that inherit the properties and methods of existing classes. This allows for code reuse and a clear hierarchy of class relationships.

An example of inheritance in Python is the use of the class DerivedClass(BaseClass): syntax to create a derived class that inherits from a base class.

class Shape:
def __init__(self, x, y):
self.x = x
self.y = y
def area(self):
return self.x * self.y

class Rectangle(Shape):
def __init__(self, x, y):
super().__init__(x, y)

class Square(Rectangle):
def __init__(self, x):
super().__init__(x, x)

sq = Square(4)
print(sq.area()) # 16

In the above example, the class Square is derived from class Rectangle, which itself is derived from class Shape. So, the class Square has access to the methods of both Rectangle and Shape classes.


Polymorphism refers to the ability of a single function or method to work with multiple types of data. This means that the same function or method can be used to work with different types of objects, even if they are instances of different classes.

There are two main types of polymorphism in Python:

Duck Typing: Duck typing is a form of polymorphism in which the type of an object is determined by the methods and properties it has, rather than by its class. This means that if an object “walks like a duck and quacks like a duck”, it is considered to be a duck.

def quack(duck):

class Duck:
def quack(self):

class Goose:
def quack(self):

duck = Duck()
goose = Goose()
quack(duck) # Quack
quack(goose) # Honk

In this example, quack function is able to work with both Duck and Goose objects, even though they are instances of different classes because they both have a quack method.

Method Overriding: Method overriding is a form of polymorphism in which a subclass can provide a different implementation of a method that is already defined in its superclass. This allows the subclass to inherit the behavior of the superclass, while also providing its own implementation.

class Animal:
def speak(self):
print("Animal make noise")

class Dog(Animal):
def speak(self):

class Cat(Animal):
def speak(self):

dog = Dog()
cat = Cat()
dog.speak() # Bark
cat.speak() # Meow

In this example, the speak method is defined in the Animal class, but Dog and Cat classes both provide their own implementation of the method. This allows the speak method to behave differently depending on the type of object it is called on.


  • Functions are one of the most important concepts in Python and are used to organize and reuse code. They can take input parameters, return output, have default values for parameters, and can be assigned to variables or used as arguments for other functions. Python also provides advanced features such as lambda functions, function decorators, and a variable number of arguments, which can be used to further enhance the functionality and readability of your code.
  • Modules are a great way to organize and reuse your Python code and can help make your code more readable, maintainable, and efficient.
  • Classes are important because they provide a way to create new data types. With classes, you can define the characteristics and behavior of a type of object, and then create instances of that object.

If you like the post, don’t forget to clap. If you’d like to connect, you can find me on LinkedIn.


Leave a Reply

Your email address will not be published.