Object Oriented Programming in Python – Classes and Objects

Object Oriented Programming (OOP) in Python is a programming paradigm that uses objects and classes. It provides a way to structure and organize code in a reusable and modular way. It allows for code organization, reusability, and encapsulation by bundling data (attributes) and behavior (methods) into objects.

Object Oriented Programming (OOP)

Object Oriented Programming (OOP) is a paradigm that allows developers to represent real-world entities as objects. These objects have properties as attributes and behaviors as methods. There are various components and benefits of Object Oriented Programming.

  • Class is a user-defined prototype or a blueprint for creating objects (instances). This defines set of attributes that characterize any object of class.
  • Object is an instance of a class with real data and behavior.
  • Attributes are data members (class variables and instance variables) and methods. attributes are accessed via dot notation

Key Principles of Object Oriented Programming (OOP):

  • Modularity means breaking code into smaller and reusable pieces.
  • Abstraction – Hiding implementation details.
  • Encapsulation – Restricting access to internal data.
  • Inheritance – Reusing existing code.
  • Polymorphism – Using a unified interface for different data types.

Classes and Objects

In Python, a Class is a user-defined prototype or a blueprint for creating objects (instances) and is defined using the class keyword. Object is an instance of a class with real data and behavior and created by calling the class like a function. Syntax to create a Class:

# class ClassName:
# 	"""class documentation string is optional"""
# 	class_attributes, variables, functions

Example of Class and Objects

# Definition of class

class Shbytes:                                         # define a class with name Shbytes
	"""Online training in various IT courses"""        # docstring for the Shbytes class

	# class level variable
	course_count = 0                                    # class level variable
	
	# __init__() is the constructor of the class
	def __init__(self, course_name, course_duration):  # initialize function for Shbytes class
		self.course_name = course_name             # course_name is Shbytes class attribute
		self.course_duration = course_duration     # course_duration is Shbytes class attribute
		Shbytes.course_count += 1                   # course_count is Shbytes class level variable
		self.course_id = "C" + str(Shbytes.course_count) # course_id is Shbytes class attribute
	
	# class functions, but first argument is self
	def totalCourses(self):                            # user-defined function in Shbytes class
		print("Total Courses - ", Shbytes.course_count)

	def courseDetails(self):                           # user-defined function in Shbytes class
		print("course id - ", self.course_id)
		print("course name - ", self.course_name)
		print("course duration - ", self.course_duration

# create object & instance of the class, with instance referring to object
print("create object & instance of the class, with instance referring to object")

shbytes1 = Shbytes("AWS", 50)     # shbytes1 is an instance of Shbytes class
shbytes2 = Shbytes("Python", 50)  # shbytes2 is second instance of Shbytes class
shbytes3 = Shbytes("ML", 60)      # shbytes3 is third instance of Shbytes class

# access attributes (class variable & functions) of a class
print("access attributes (class variable & functions) of a class")

shbytes1.courseDetails()           # call courseDetails() using shbytes1 instance
shbytes2.courseDetails()           # call courseDetails() using shbytes2 instance
shbytes2.totalCourses()            # call totalCourses() using shbytes2 instance

Let’s understand this program in three sections – Definition of Class, Create instances of Class and call functions of Class.

  1. Definition of Class
    • Using class Shbytes: defines a class. Shbytes is the name of the class.
    • First line of this class is the docstring (like a documentation) for this class.
    • course_count is a Class level variable, it means course_count can be accessed with the class name and its value will be common (shared) with all instances.
    • In Python, every class is initialized using the __init__() function. This is like a constructor for the class. This defines the attributes (fields) available in the class and can assign value to those attributes. In this example, course_name, course_duration and course_id are the attributes of Shbytes class.
    • Two user-defines functions totalCourses(self) and courseDetails(self) are defined for Shbytes class. self is the first argument for these functions.
  2. Create instances (objects) of Class
    • Using shbytes1 = Shbytes("AWS", 50), shbytes2 = Shbytes("Python", 50) and shbytes3 = Shbytes("ML", 60), we have created the three instances of Shbytes Class.
    • Each instance of the class are run on different threads, has their own value for class attributes and has their own life-cycle.
  3. Calling functions of Class
    • We can call the class functions using the class instance and the function name.
    • shbytes1.courseDetails() – This makes a call to the courseDetails() function with shbytes1 instance. It means, all attribute values will be based on shbytes1 instance.
    • shbytes2.courseDetails() and shbytes2.totalCourses(), make call functions with shbytes2 instance. All attribute values will be based on shbytes2 instance.

Attributes on Class Object

Python has provide built-in methods to access, update and delete attributes values on class object.

  • hasattr(*args, **kwargs) return True or False, based on the object has an attribute with the given name or not. This is validated by calling getattr(obj, name) and catching AttributeError.
  • getattr(object, attributeName, default=None) – This is used to get the value of named attribute from an object. This is equivalent to object.attributeName. If default argument is given, it is returned when the attribute doesn’t exist; otherwise, an exception is raised in that case.
  • setattr(object, attributeName, value) – This sets the specified value for the attribute on the given object. This is equivalent to object.attributeName = value.
  • delattr(object, attributeName) – This deletes the named attribute from the given object. This is equivalent to del object.attributeName

Example to access, update and delete attributes on class object

# validate if object has given attribute
print(hasattr(shbytes1, 'course_name'))  # validate if shbytes1 object has course_name attribute

# get attribute value for the object
print(getattr(shbytes1, 'course_id'))    # get value of course_id attribute for shbytes1 object
print(shbytes1.course_id)                # get value of course_id attribute for shbytes1 object

# set attribute value for the object
setattr(shbytes3, 'course_duration', 70) # set value of course_duration attribute for shbytes3 object

# delete attribute for the object
delattr(shbytes3, 'course_duration')     # delete course_duration attribute for shbytes3 object

try:
	print(getattr(shbytes3, 'course_duration')) # Try accessing attribute after delete
except AttributeError as err:
	print("error", err)

Built-in Class Attributes

  • __dict__ gives dictionary containing class namespace
  • __doc__ gives class documentation string or none, if undefined
  • __name__ gives class name
  • __module__ gives module name in which this class is defined
  • __bases__ possibly empty tuple containing the base classes, in the order of their occurrence in the base class list
# __dict__ - gives dictionary containing class namespace
print ("shbytes.__dict__ => ", Shbytes.__dict__)      # dictionary of Shbytes class namespace

# __doc__ - gives class documentation string or none, if undefined
print ("shbytes.__doc__ => ", Shbytes.__doc__)       # Shbytes class documentation string

# __name__ - gives class name
print ("shbytes.__name__ => ", Shbytes.__name__)     # Shbytes class name

# __module__ - gives module name in which this class is defined
# This attribute is __main__ in interactive mode
print ("shbytes.__module__ => ", Shbytes.__module__) # Shbytes class module name

# __bases__ - possibly empty tuple containing the base classes, in the order of their occurrence in the base class list
print ("shbytes.__bases__ => ", Shbytes.__bases__)   # tuple for Shbytes class base classes

Program Output

shbytes.__dict__ =>  {'__module__': '__main__', '__doc__': 'Online training in various IT courses', 'courseCount': 3, '__init__': <function Shbytes.__init__ at 0x000002191EE54AE0>, 'totalCourses': <function Shbytes.totalCourses at 0x000002191EE54C20>, 'courseDetails': <function Shbytes.courseDetails at 0x000002191EE54D60>, '__dict__': <attribute '__dict__' of 'Shbytes' objects>, '__weakref__': <attribute '__weakref__' of 'Shbytes' objects>}

shbytes.__doc__ =>  Online training in various IT courses

shbytes.__name__ =>  Shbytes

shbytes.__module__ =>  __main__

shbytes.__bases__ =>  (<class 'object'>,)

Delete Objects

In Python, objects can be deleted using the del keyword. After deleting an object, it gets garbage collected. Garbage collection in Python refers to the process of automatically freeing up memory by destroying objects that are no longer in use. This ensures that memory is used efficiently, preventing memory leaks.

# delete object of a class
del shbytes3

try:
	shbytes3.courseDetails() # shbytes3 object does not exists raise NameError
except NameError as err:     # catch NameError
	print("error", err)

Summary

In this article, we learned about Object Oriented Programming concepts. We learned about Classes and Objects. Following topics were discussed:

Code – Github Repository

All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.

Python Topics


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *