๐Ÿ“ ๐Ÿš€ Object-Oriented Programming (OOP) in Python#

Python OOP

Welcome & Overview#

Object-oriented programming allows you to code like an engineer, you can break problems into small parts and solve them one by one. This is a very powerful way to write code, and itโ€™s the way most professional programmers write code.

  1. Engineering Context

  • In mechanical, electrical, or industrial systems, well-structured software design is critical for reliability and scalability.

  • OOP provides a systematic approach to model complex engineering processes (robotic arms, conveyor lines, control systems).

  1. Why OOP Matters in Engineering

  • Modularity: Keep hardware interface code, logic, and data well-organized.

  • Scalability: As systems grow in complexity (more sensors, more machines), OOP architectures scale more gracefully.

OOP and the Engineering Analogy#

- Classes are like blueprints in engineering:
    - Define the shape, structure, and potential behaviors.
- Objects are actual machines or components built from those blueprints.

Example#

  • A RobotArm class might define the dimensions, motor details, and control functions.

  • Each object is a specific robotic arm installed on the production floor with its own parameters (e.g., arm length, motor torque).

What is OOP? ๐Ÿค–#

OOP organizes real-world entities in code via classes and objects.

Key Benefits in Engineering

  • Clean Architecture: Clear boundaries between software modules (e.g., sensor data handling, actuator control).

  • Maintainability: System components can be updated or replaced with minimal impact on the rest of the system.

  • Testability: Classes can be unit-tested individually, which is critical in safety-critical engineering applications.

Sample Code

class Machine:
    def __init__(self, name, operator):
        self.name = name
        self.operator = operator

    def operate(self):
        return f"Machine '{self.name}' operated by {self.operator} is running."


machine_a = Machine("Hydraulic Press", "Alice")
machine_b = Machine("Laser Cutter", "Bob")

print(machine_a.operate())
print(machine_b.operate())
Machine 'Hydraulic Press' operated by Alice is running.
Machine 'Laser Cutter' operated by Bob is running.

Four Pillars of OOP โ€” Overview#

  1. Encapsulation โ€“ Hiding internal details (like embedded controller internals).

  1. Inheritance โ€“ Building specialized machines from a base machine blueprint.

  1. Polymorphism โ€“ Common methods that behave differently for varied components (e.g., different sensors).

  1. Abstraction โ€“ Providing a simplified interface to complex systems (e.g., a single API for controlling multiple machine types).

Polymorphism and Abstraction you can think of like an on button. You can have on button actions for a lot of different machines, but they all do different things.

Encapsulation ๐Ÿค#

Engineering Analogy:

  • Think of encapsulation like hiding sensitive internal schematics or proprietary control algorithms.

  • Only expose external interfaces needed to operate or monitor the machine, keeping the implementation protected.

Code Example

class MotorController:
    def __init__(self):
        self.__firmware_version = "v3.14"  # Private detail

    def get_firmware_info(self):
        return "Firmware details are restricted to authorized personnel."
# Python doesn't enforce privacy strictly, but name-mangling is a common convention:
controller = MotorController()
# This will still work (though discouraged):
print(controller._MotorController__firmware_version)  # "v3.14"
v3.14

Key Takeaway

  • Encapsulation maintains system integrity: internal states and methods remain controlled, preventing accidental misuse.

  • a user is must less likely to accidently change _something than something itself.

Inheritance ๐Ÿ‘ถ#

Engineering Analogy:

  • A Base Robot class might define universal properties (e.g., number of axes, control loops).

  • Specialized Robots (like welding robots or painting robots) inherit and extend the base class.

Code Example

class BaseMachine:
    def __init__(self, name):
        self.name = name

    def operate(self):
        return f"Machine '{self.name}' is operating in a basic mode."


class CNC_Machine(BaseMachine):
    def __init__(self):
        super().__init__("CNC Machine")

    def operate(self):
        return super().operate() + " (Executing CNC-specific routines.)"


cnc = CNC_Machine()
print(cnc.operate())
Machine 'CNC Machine' is operating in a basic mode. (Executing CNC-specific routines.)

Key Takeaway

  • super() lets the derived class reuse and extend parent functionality.

  • In large engineering systems, inheritance avoids rewriting shared functionality.

Polymorphism ๐ŸŽญ#

Engineering Analogy:

  • Different sensors (temperature, pressure, flow) can each implement a read_data() method.

  • The controlling system calls sensor.read_data() without worrying about sensor internals.

Code Example

class TemperatureSensor:
    def read_data(self):
        return "Temperature data in ยฐC"


class PressureSensor:
    def read_data(self):
        return "Pressure data in bar"


def perform_reading(sensor):
    print(sensor.read_data())


temp_sensor = TemperatureSensor()
press_sensor = PressureSensor()

perform_reading(temp_sensor)  # Temperature data in ยฐC
perform_reading(press_sensor)  # Pressure data in bar
Temperature data in ยฐC
Pressure data in bar

Key Takeaway

  • Polymorphism supports extensibility: new device types can be added without modifying existing code.

Abstraction ๐Ÿ•ต๏ธโ€โ™‚๏ธ#

โ€œJust give me a single control API; donโ€™t worry about the details.โ€

Engineering Analogy:

  • A factory automation system might define a general MachineInterface.

  • Individual machine types (e.g., conveyor belts, robotic arms, CNCs) implement the abstract functions differently.

Code Example

from abc import ABC, abstractmethod


class MachineInterface(ABC):
    @abstractmethod
    def start(self):
        pass


class ConveyorBelt(MachineInterface):
    def start(self):
        return "Conveyor Belt running at 1.5 m/s"


class RoboticArm(MachineInterface):
    def start(self):
        return "Robotic Arm initialized with 6 degrees of freedom"


def initialize_machine(machine):
    print(machine.start())


conveyor = ConveyorBelt()
roboticarm = RoboticArm()

initialize_machine(conveyor)  # Conveyor Belt running at 1.5 m/s
initialize_machine(roboticarm)  # Robotic Arm initialized with 6 degrees of freedom
Conveyor Belt running at 1.5 m/s
Robotic Arm initialized with 6 degrees of freedom

Key Takeaway

  • Abstraction enforces a standard interface for different subclasses, streamlining operations in large facilities.

OOP in Real-World Engineering#

  • Encapsulation

    • PLCs (Programmable Logic Controllers) often have protected internal logic, with only certain parameters modifiable.

  • Inheritance

    • Base class for sensor types; specialized classes for temperature, pressure, or motion sensors.

  • Polymorphism

    • A universal read() method used by different sensor or actuator classes.

  • Abstraction

    • High-level โ€œstart_machine()โ€ API used by operators, hiding the underlying complexities of each subsystem.

Why Engineers Care - Reduces duplication in massive codebases for industrial systems. - Eases maintenance and upgradesโ€”add new machinery or sensors without breaking existing logic.

Recap โ€” Engineering Edition#

OOP Concept

Engineering Analogy

Benefit

Encapsulation

Hiding internal controller details

Controlled data access, better safety

Inheritance

Specialized robots from a base robot class

Shared functionality, easy extension

Polymorphism

Common interface for different sensor types

Uniform handling, flexible system integration

Abstraction

Single control API for varied machine types

Simpler user interface, hides complexity