1. Introduction
Object-Oriented Programming (OOP) organizes code around objects, which bundle data (attributes) and behavior (methods) together. Python supports OOP natively, and nearly everything in it, including integers, strings, and lists, in an object.
Using libraries and randint()
Python's standard library provides ready-made tools through the import statement. The random module is a common example:
import random
roll = random.randint(1, 6) # random integer from 1 to 6, inclusive
print(roll)
Here, random is a module (an object), and randint() is a method of it. You can also import a single function directly:
from random import randint
print(randint(1, 100))
Attributes are values stored on an object (e.g.,
car.color).Methods are functions defined inside a class that act on the object (e.g.,
car.drive()).
2. Classes and Objects
A class is a blueprint. An object (or instance) is something built from that blueprint.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name} says woof!"
mutina = Dog("Mutina", 3)
print(mutina.bark()) # Mutina says woof!
What is __init__? It is the constructor, a special method that runs automatically when an object is created. It sets up the object's initial state.
What is self? It refers to the specific instance being worked on. When you call mutina.bark(), Python passes mutina in as self, so each object keeps its own data.
3. Class Attributes vs. Instance Attributes
class Dog:
species = "Canis familiaris" # class attribute (shared)
def __init__(self, name):
self.name = name # instance attribute (unique)
a = Dog("Rex")
b = Dog("Bosco")
print(a.species, b.species) # shared value
print(a.name, b.name) # different values
Class attributes belong to the class and are shared by all instances.
Instance attributes belong to one object and are defined via
self(usually in__init__).
4. Methods
Python has three kinds of methods:
class Circle:
pi = 3.14159
def __init__(self, radius):
self.radius = radius
def area(self): # instance method
return self.pi * self.radius ** 2
@classmethod
def unit(cls): # class method
return cls(1)
@staticmethod
def is_valid(radius): # static method
return radius > 0
Instance methods use
selfand work with object data.Class methods use
clsand work with the class itself.Static methods need neither; they are utility functions grouped with the class.
5. Parent and Child Classes
A parent (base) class provides shared features. A child (derived) class inherits them and can add or override behavior.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "Some sound"
class Cat(Animal): # Cat is the child of Animal
def __init__(self, name, indoor):
super().__init__(name) # reuse the parent's setup
self.indoor = indoor
def speak(self): # overide
return f"{self.name} says meow"
super() gives the child access to the parent's methods.
6. The Four Pillars of OOP
Encapsulation bundles data and methods together and restricts direct access to internal state. Python uses naming conventions: _name (protected by convention) and __name (name-mangled, "private").
class BankAccount:
def __init__(self, balance):
self.__balance = balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def get_balance(self):
return self.__balance
Inheritance lets a class reuse and extend another class's code, reducing duplication.
Polymorphism means different classes can respond to the same method call in their own way.
class Dog:
def speak(self): return "Woof"
class Cat:
def speak(self): return "Meow"
for pet in (Dog(), Cat()):
print(pet.speak()) # same call, different behavior
Abstraction hides complexity and exposes only what is neccessary. Python implements it with abstract base classes:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
Shape cannot be intantiated directly; every child must implement area().
7. Types of Python Errors
| Type | When it occurs | Example |
|---|---|---|
| Syntax error | Code breaks Python's grammar; the priogram won't start |
print("Hi"(missing parenthesis) |
| Runtime error | Code is valid but fails while running | 10 / 0 |
| Logical error | Code runs without crashing but produces wrong results | Using + instead of * in a formula |
Logical errors are the hardest to find because Python raises no warning. Testing and print() or debugger inspection are the best defenses.
8. Error Handling with try/except
try:
number = int(input("Enter a number: "))
print(10 / number)
except ValueError:
print("That is not a valid number.")
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print("Success!") # runs only if no exception occurred
finally:
print("Done.") # always runs
try: code that might failexcept: handles a specific errorelse: runs if nothing went wrongfinally: runs no matter what (ideal for cleanup)
You can also raise your own exceptions with raise ValueError("Invalid input").
9. Common Python Exceptions
ZeroDivisionError: dividing by zero.
print(5 / 0)
ValueError: right type, inappropriate value.
int("abc")
TypeError: an operation applied to the wrong type.
"5" + 3
NameError: using a variable that hasn't been defined.
print(undefined_var)
IndexError: accessing a list position that doesn't exist.
items = [1, 2, 3]
print(items[5])
FileNotFoundError: opening a file that doesn't exist.
open("missing.txt")
Conclusion
Object-oriented programming gives Python developers a clean way to model real-world problems: classes define structure, objects hold state, and the four pillars keep code organized, reusable, and secure. Paired with disciplined error handling, which anticipates syntax, runtime, and logical failures and catches common exceptions gracefully, these skills form the foundation of professional, maintainable Python code.
Top comments (0)