Python 2.7.x - trying to get the hang of OOP and classes
Categories:
Mastering Python 2.7.x OOP: A Comprehensive Guide to Classes and Objects

Dive into Object-Oriented Programming (OOP) in Python 2.7.x. This guide covers classes, objects, inheritance, and polymorphism with practical examples to solidify your understanding.
Object-Oriented Programming (OOP) is a fundamental paradigm that structures software around data, or objects, rather than functions and logic. While Python 2.7.x is an older version, understanding its approach to OOP provides a strong foundation for grasping modern Python's object model. This article will walk you through the core concepts of classes, objects, attributes, methods, inheritance, and polymorphism, specifically tailored for Python 2.7.x.
The Basics: Classes and Objects
At the heart of OOP are classes and objects. 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). An object is an instance of a class. Think of a class as a cookie cutter and objects as the cookies it produces. Each cookie (object) has the same shape (structure defined by the class) but can have different toppings (attribute values).
class Dog:
# Class attribute
species = "Canis familiaris"
# Initializer / Instance attributes
def __init__(self, name, age):
self.name = name
self.age = age
# Instance method
def bark(self):
return "Woof! My name is {} and I am {} years old.".format(self.name, self.age)
# Creating objects (instances of the Dog class)
my_dog = Dog("Buddy", 3)
your_dog = Dog("Lucy", 5)
print my_dog.name # Output: Buddy
print your_dog.age # Output: 5
print my_dog.species # Output: Canis familiaris
print my_dog.bark() # Output: Woof! My name is Buddy and I am 3 years old.
Defining a simple class and creating objects in Python 2.7.x
object
for 'new-style' classes, though it's often omitted for simplicity in basic examples. For example: class Dog(object):
.Understanding Inheritance and Polymorphism
Inheritance allows a class (child or subclass) to inherit attributes and methods from another class (parent or superclass). This promotes code reusability and establishes a natural hierarchy. Polymorphism, meaning 'many forms', allows objects of different classes to be treated as objects of a common type. In Python, this is often achieved through method overriding and duck typing (if it walks like a duck and quacks like a duck, then it's a duck).
classDiagram Animal <|-- Dog Animal <|-- Cat Animal : +str name Animal : +int age Animal : +make_sound() Dog : +bark() Cat : +meow()
Class diagram illustrating inheritance between Animal, Dog, and Cat classes.
class Animal(object):
def __init__(self, name):
self.name = name
def make_sound(self):
raise NotImplementedError("Subclass must implement abstract method")
class Dog(Animal):
def __init__(self, name, breed):
super(Dog, self).__init__(name) # Python 2.7.x super() call
self.breed = breed
def make_sound(self):
return "Woof!"
class Cat(Animal):
def __init__(self, name, color):
super(Cat, self).__init__(name) # Python 2.7.x super() call
self.color = color
def make_sound(self):
return "Meow!"
# Polymorphism in action
def animal_action(animal):
print "{} says: {}".format(animal.name, animal.make_sound())
my_dog = Dog("Rex", "German Shepherd")
my_cat = Cat("Whiskers", "Tabby")
animal_action(my_dog) # Output: Rex says: Woof!
animal_action(my_cat) # Output: Whiskers says: Meow!
Demonstrating inheritance and polymorphism in Python 2.7.x
super()
function in Python 2.7.x requires explicit arguments (super(ChildClass, self).__init__(...)
) unlike Python 3, where it can be called without arguments.Encapsulation and Data Hiding
Encapsulation is the bundling of data (attributes) and methods that operate on the data into a single unit, or class. It also involves restricting direct access to some of an object's components, which is known as data hiding. While Python doesn't have strict private keywords like Java or C++, it uses conventions to indicate that an attribute or method is intended for internal use. A single leading underscore (_attribute
) suggests it's protected (should not be accessed directly from outside the class), and a double leading underscore (__attribute
) triggers name mangling, making it harder to access directly and effectively 'private' within the class.
class BankAccount:
def __init__(self, initial_balance):
self.__balance = initial_balance # 'Private' attribute due to name mangling
self._account_number = "12345" # Protected attribute
def deposit(self, amount):
if amount > 0:
self.__balance += amount
print "Deposited {}. New balance: {}".format(amount, self.__balance)
else:
print "Deposit amount must be positive."
def get_balance(self):
return self.__balance
my_account = BankAccount(100)
my_account.deposit(50) # Output: Deposited 50. New balance: 150
# Attempting to access 'private' attribute directly (will cause AttributeError or mangled access)
# print my_account.__balance # This will raise an AttributeError
print my_account._BankAccount__balance # This works, but is not recommended
print my_account.get_balance() # Output: 150
print my_account._account_number # Accessing protected attribute (conventionally discouraged)
Illustrating encapsulation and Python's approach to data hiding