Python Classes & Objects: Object-Oriented AI
Master Python classes and objects, the foundation of object-oriented programming crucial for building modular AI and machine learning applications. Learn to create blueprints for your data.
6.2 Python Classes and Objects
Python is a powerful object-oriented programming language where everything, from basic data types like integers and strings to complex user-defined structures, is treated as an object. This object-oriented approach promotes clean, modular, and reusable code.
What is a Class in Python?
A class in Python serves as a blueprint or template for creating objects. It encapsulates attributes (data) and methods (functions) that define the behavior and state of the objects created from it.
For instance, a Smartphone
class could have attributes like brand
, RAM
, and storage
, and methods like make_call()
or send_message()
.
How to Define a Class in Python
You use the class
keyword to define a class. The general syntax is:
class ClassName:
"""Optional documentation string describing the class."""
# class body: attributes (variables) and methods (functions)
Example: A Basic Python Class
Here's an example of an Employee
class:
class Employee:
"""Base class for all employees."""
empCount = 0 # Class variable: shared across all instances of the class
def __init__(self, name, salary):
"""
Constructor method to initialize instance attributes.
"""
self.name = name # Instance variable: unique to each object
self.salary = salary # Instance variable: unique to each object
Employee.empCount += 1
def show_count(self):
"""Displays the total number of employees."""
print(f"Total Employees: {Employee.empCount}")
def show_details(self):
"""Displays the details of an employee."""
print(f"Name: {self.name} | Salary: {self.salary}")
Explanation of the Employee
class:
empCount = 0
: This is a class variable. It's shared among all instances of theEmployee
class. When a new employee is created, this count is incremented.__init__(self, name, salary)
: This is the constructor method. It's automatically called when you create a new object (instance) of the class.self
refers to the instance of the class being created.self.name = name
andself.salary = salary
are instance variables. Each object created from the class will have its own uniquename
andsalary
.Employee.empCount += 1
increments the class variableempCount
for every new employee object.
show_count(self)
: A method that accesses and prints the class variableempCount
.show_details(self)
: A method that accesses and prints the instance variablesname
andsalary
for a specific employee object.
Creating Objects (Instances) from a Class
Once a class is defined, you can create objects (instances) from it by calling the class name as if it were a function.
# Create instances of the Employee class
emp1 = Employee("Alice", 3000)
emp2 = Employee("Bob", 4000)
# Call methods on the objects
emp1.show_details() # Output: Name: Alice | Salary: 3000
emp2.show_details() # Output: Name: Bob | Salary: 4000
emp1.show_count() # Output: Total Employees: 2
Working with Object Attributes
Python allows for dynamic manipulation of object attributes: you can add, modify, or delete attributes of an object after it has been created.
emp1 = Employee("Alice", 3000)
# Add a new attribute dynamically
emp1.age = 25
print(f"Alice's age: {emp1.age}") # Output: Alice's age: 25
# Modify an existing attribute
emp1.salary = 3500
print(f"Alice's new salary: {emp1.salary}") # Output: Alice's new salary: 3500
# Delete an attribute
del emp1.age
# print(emp1.age) # This would now raise an AttributeError
Using Built-in Functions to Manage Attributes
Python provides several built-in functions to interact with object attributes:
getattr(obj, attr_name[, default])
: Retrieves the value of an attribute. If the attribute doesn't exist, it returnsdefault
if provided, otherwise raises anAttributeError
.setattr(obj, attr_name, value)
: Sets or creates an attribute on an object.hasattr(obj, attr_name)
: Checks if an object has a specified attribute, returningTrue
orFalse
.delattr(obj, attr_name)
: Deletes a specified attribute from an object.
emp1 = Employee("Alice", 3000)
# Example using getattr with a default value
print(getattr(emp1, 'department', 'HR')) # Output: HR (since 'department' doesn't exist)
# Example using setattr to add an attribute
setattr(emp1, 'department', 'Sales')
print(f"Alice's department: {getattr(emp1, 'department')}") # Output: Alice's department: Sales
# Example using hasattr
print(hasattr(emp1, 'age')) # Output: False (if 'age' was deleted or never added)
# Example using delattr
if hasattr(emp1, 'department'):
delattr(emp1, 'department')
print(hasattr(emp1, 'department')) # Output: False
Python Built-in Class Attributes
Every class in Python has several special attributes that provide metadata about the class itself.
Attribute | Description |
---|---|
__dict__ | Dictionary containing the class's namespace. |
__doc__ | String containing the class's documentation (docstring). |
__name__ | String containing the class's name. |
__module__ | String containing the name of the module where the class is defined. |
__bases__ | Tuple containing the base classes of the current class (for inheritance). |
# Accessing built-in class attributes
print(f"Docstring: {Employee.__doc__}") # Output: Docstring: Base class for all employees.
print(f"Class Name: {Employee.__name__}") # Output: Class Name: Employee
print(f"Module: {Employee.__module__}") # Output: Module: __main__ (if run as a script)
print(f"Base Classes: {Employee.__bases__}") # Output: Base Classes: (<class 'object'>,)
# print(f"Dictionary: {Employee.__dict__}") # This will print a large dictionary of class attributes and methods
Checking an Object’s Type
The type()
function is used to determine the class (type) of any object.
print(type(42)) # Output: <class 'int'>
print(type(3.14)) # Output: <class 'float'>
print(type("Python")) # Output: <class 'str'>
print(type([1, 2, 3])) # Output: <class 'list'>
print(type({'x': 1, 'y': 2})) # Output: <class 'dict'>
emp1 = Employee("Alice", 3000)
print(type(emp1)) # Output: <class '__main__.Employee'>
Memory Management and Garbage Collection
Python employs automatic memory management and garbage collection. When an object no longer has any references pointing to it, Python's garbage collector automatically reclaims the memory occupied by that object.
# Example of reference counting and garbage collection
a = 10 # 'a' references the integer object 10
b = a # 'b' now also references the integer object 10
c = [b] # 'c' references a list containing a reference to 10
del a # Reference from 'a' to 10 is removed
del b # Reference from 'b' to 10 is removed
# The integer object 10 is now only referenced by the list in 'c'.
# If 'c' is also deleted or its reference to 10 is removed, the object 10 might be garbage collected.
c[0] = 0 # The list now references 0, breaking the link to the original 10
c = None # The list object itself is no longer referenced
# The integer object 10 is now unreferenced and eligible for garbage collection.
Using Destructors with __del__()
You can define a special method, __del__()
, within a class to perform custom cleanup actions when an object is about to be destroyed (garbage collected).
class Resource:
def __init__(self, name):
self.name = name
print(f"Resource '{self.name}' created.")
def __del__(self):
"""Destructor method for custom cleanup."""
print(f"Resource '{self.name}' is being released (garbage collected).")
# Create an object
r1 = Resource("FileHandle")
# The __del__ method is called automatically when the object is no longer referenced.
# This can happen when the object goes out of scope or is explicitly deleted.
del r1
# Output: Resource 'FileHandle' is being released (garbage collected).
Note: While __del__
can be useful, relying on it for critical cleanup can be tricky due to the non-deterministic nature of garbage collection. For robust resource management, context managers (with
statement) are often preferred.
Data Hiding in Python using Name Mangling
Python doesn't have strict private/public access modifiers like some other languages. However, it provides a mechanism called name mangling to simulate data hiding. By prefixing an attribute name with double underscores (__
), Python modifies the attribute's name internally, making it harder to access directly from outside the class.
class Counter:
def __init__(self):
self.__hidden_count = 0 # Name mangling: __hidden_count becomes _Counter__hidden_count
def increment(self):
self.__hidden_count += 1
print(f"Incremented to: {self.__hidden_count}")
# Create an instance
c = Counter()
c.increment() # Output: Incremented to: 1
c.increment() # Output: Incremented to: 2
# Direct access from outside the class will raise an AttributeError
# try:
# print(c.__hidden_count)
# except AttributeError as e:
# print(e) # Output: 'Counter' object has no attribute '__hidden_count'
# Accessing the "mangled" attribute (not recommended for regular use)
print(f"Accessing mangled attribute: {c._Counter__hidden_count}") # Output: Accessing mangled attribute: 2
Key takeaway: Using double underscores (__
) in front of a variable name within a class is a convention to indicate that the attribute is intended for internal use and to prevent accidental modification or access from outside the class.
SEO Keywords
- Python classes tutorial
- Python object creation
- Python instance vs class variables
- Python object attributes
- Python built-in class attributes
- Python
getattr
,setattr
- Python type checking
- Python memory management
- Python destructors example (
__del__
) - Python name mangling
Interview Questions
- What is a class in Python and how is it different from an object?
- A class is a blueprint or template, while an object is an instance created from that blueprint.
- How do class variables and instance variables differ? Give examples.
- Class variables are shared among all instances (e.g.,
Employee.empCount
), while instance variables are unique to each object (e.g.,emp1.name
).
- Class variables are shared among all instances (e.g.,
- Explain the use of the
__init__()
method in Python.- It's the constructor method, automatically called when an object is created to initialize its attributes.
- How can you dynamically add, modify, or delete object attributes in Python?
- Using direct assignment (
obj.attr = value
), modification (obj.attr = new_value
), or thedelattr()
function anddel obj.attr
syntax.
- Using direct assignment (
- What are
getattr()
,setattr()
,hasattr()
, anddelattr()
used for?- They are built-in functions for dynamically accessing, setting, checking for, and deleting object attributes, respectively.
- What is the purpose of built-in class attributes like
__dict__
,__doc__
, and__module__
?- They provide metadata about the class itself, such as its namespace, documentation, and origin module.
- How does Python handle memory management and garbage collection?
- Python uses automatic garbage collection, which reclaims memory from objects that are no longer referenced.
- What is the role of the
__del__()
method in Python?- It's a destructor method that can be defined to perform cleanup actions just before an object is garbage collected.
- How do you check the type of an object in Python?
- Using the built-in
type()
function.
- Using the built-in
- What is name mangling in Python and how does it help in data hiding?
- Name mangling (prefixing attributes with
__
) internally renames attributes to a less predictable format (_ClassName__attributeName
), making them difficult to access directly from outside the class, thus simulating private members.
- Name mangling (prefixing attributes with
Python OOP Concepts: Object-Oriented Programming Explained
Master Python OOP concepts: classes, objects, inheritance, and polymorphism. Build efficient, reusable code for AI & ML projects with this comprehensive guide.
Python Constructors & Instance Methods for AI Dev
Master Python constructors (__init__) and instance methods! Essential for object-oriented programming and building AI/ML applications efficiently. Learn best practices.