Python classes serve as the cornerstone of object-oriented programming (OOP), allowing programmers to define the blueprint for creating objects. A class encapsulates both data (attributes) and functionalities (methods) that operate on the data. Defined using the class
keyword, a class contains an optional constructor method called __init__
for initializing attributes, and can also have other methods for manipulating these attributes or performing tasks. Following are the coding patterns for python classes.
- Singleton Pattern for Python Classes:
The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
# Usage
instance1 = Singleton()
instance2 = Singleton()
print(instance1 is instance2) # Output: True
- Factory Pattern for Python Classes::
The Factory pattern creates objects without specifying the exact class of object that will be created.
class Dog:
def speak(self):
return "Woof!"
class Cat:
def speak(self):
return "Meow!"
class AnimalFactory:
def create_animal(self, animal_type):
if animal_type == "dog":
return Dog()
elif animal_type == "cat":
return Cat()
# Usage
factory = AnimalFactory()
animal = factory.create_animal("dog")
print(animal.speak()) # Output: Woof!
- Observer Pattern:
The Observer pattern defines a dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
class Observer:
def update(self, message):
pass
class ConcreteObserver(Observer):
def update(self, message):
print("Received message:", message)
class Subject:
_observers = []
def attach(self, observer):
self._observers.append(observer)
def notify_observers(self, message):
for observer in self._observers:
observer.update(message)
# Usage
subject = Subject()
observer1 = ConcreteObserver()
observer2 = ConcreteObserver()
subject.attach(observer1)
subject.attach(observer2)
subject.notify_observers("Hello, observers!")
- Decorator Pattern:
The Decorator pattern allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.
class Coffee:
def cost(self):
return 5
class MilkDecorator:
def __init__(self, coffee):
self._coffee = coffee
def cost(self):
return self._coffee.cost() + 2
# Usage
simple_coffee = Coffee()
milk_coffee = MilkDecorator(simple_coffee)
print(milk_coffee.cost()) # Output: 7
- Strategy Pattern:
The Strategy pattern defines a family of algorithms, encapsulates each algorithm, and makes them interchangeable. This allows a client to choose an algorithm from a family of algorithms at runtime.
class Strategy:
def execute(self, a, b):
pass
class Add(Strategy):
def execute(self, a, b):
return a + b
class Subtract(Strategy):
def execute(self, a, b):
return a - b
class Context:
def __init__(self, strategy):
self._strategy = strategy
def execute_strategy(self, a, b):
return self._strategy.execute(a, b)
# Usage
add_strategy = Add()
context = Context(add_strategy)
result = context.execute_strategy(5, 3)
print(result) # Output: 8
- Template Method Pattern:
The Template Method pattern defines the structure of an algorithm in a base class but lets subclasses override specific steps of the algorithm without changing its structure.
class Template:
def template_method(self):
self.step_one()
self.step_two()
def step_one(self):
pass
def step_two(self):
pass
class ConcreteTemplate(Template):
def step_one(self):
print("Step one")
def step_two(self):
print("Step two")
# Usage
template = ConcreteTemplate()
template.template_method()
- Iterator Pattern:
The Iterator pattern provides a way to access the elements of a collection without exposing its underlying representation.
class Iterator:
def __init__(self, collection):
self._collection = collection
self._index = 0
def __next__(self):
if self._index < len(self._collection):
item = self._collection[self._index]
self._index += 1
return item
raise StopIteration
class Collection:
def __init__(self):
self._items = []
def add_item(self, item):
self._items.append(item)
def __iter__(self):
return Iterator(self._items)
# Usage
collection = Collection()
collection.add_item("Item 1")
collection.add_item("Item 2")
for item in collection:
print(item)
- Command Pattern:
The Command pattern encapsulates a request as an object, thereby allowing for parameterization of clients with different requests, queuing of requests, and logging of the requests.
class Command:
def execute(self):
pass
class Light:
def turn_on(self):
print("Light is on")
def turn_off(self):
print("Light is off")
class LightOnCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.turn_on()
class LightOffCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.turn_off()
class RemoteControl:
def __init__(self):
self._command = None
def set_command(self, command):
self._command = command
def press_button(self):
self._command.execute()
# Usage
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
remote = RemoteControl()
remote.set_command(light_on)
remote.press_button() # Output: Light is on
remote.set_command(light_off)
remote.press_button() # Output: Light is off
- Adapter Pattern:
The Adapter pattern allows objects with incompatible interfaces to collaborate.
class EuropeanSocket:
def voltage(self):
return 230
class AmericanSocket:
def voltage(self):
return 120
class AmericanToEuropeanAdapter(EuropeanSocket):
def __init__(self, american_socket):
self._american_socket = american_socket
def voltage(self):
return self._american_socket.voltage() * 2
# Usage
american_socket = AmericanSocket()
adapter = AmericanToEuropeanAdapter(american_socket)
print(adapter.voltage()) # Output: 240
- Facade Pattern:
The Facade pattern provides a unified interface to a set of interfaces in a subsystem. It defines a higher-level interface that makes the subsystem easier to use.
class SubsystemA:
def operation_a(self):
return "Subsystem A operation"
class SubsystemB:
def operation_b(self):
return "Subsystem B operation"
class Facade:
def __init__(self):
self._subsystem_a = SubsystemA()
self._subsystem_b = SubsystemB()
def operation(self):
result = []
result.append
FAQ on Python Classes
1. What is a Class in Python?
A class in Python is a blueprint for creating objects. Classes encapsulate data for the object and methods to manipulate that data. The class is defined using the class
keyword followed by the name of the class and a colon.
Example:
class MyClass:
x = 5
2. How Do I Create an Object of a Class?
Once a class is defined, you can create an object of that class using the class name followed by parentheses.
Example:
my_object = MyClass()
print(my_object.x) # Output will be 5
3. What is the __init__
Method?
The __init__
method is a special method in Python classes, also known as the “constructor.” It’s automatically called when you create a new object of a class. The method is useful for any initialization you want to do with your object.
Example:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
To create an object of this class, you would do:
person1 = Person("John", 30)
4. What is Inheritance in Python?
Inheritance allows a class to inherit attributes and methods from another class. The class inheriting is known as the “subclass,” and the class being inherited from is known as the “superclass.”
Example:
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self.grade = grade
In this example, Student
is a subclass of Person
and inherits its __init__
method.
5. What is the Difference Between Class Variables and Instance Variables?
- Class Variables: These are variables that are shared among all instances (objects) of a class. They are defined within the class but outside any methods. Example:
class MyClass:
class_var = "I'm a class variable"
- Instance Variables: These variables are unique to each instance of a class. They are defined within methods and are attached to the
self
keyword. Example:
class MyClass:
def __init__(self, x):
self.instance_var = x