""" A short description of the 3 main programming paradigms in Python - Object Oriented Programming - OOP - Procedure Oriented Programming - POP - Functional programming """ # Object Oriented Programming - OOP # This style of programming revolves around objects (classes) as the key element. # Advantages # - Easy to describe real world objects and capabilities. # - Easy to reuse code # - Easy to abstract # Disadvantages # - Hard to data protect # - Can't be used for all types of problems # - Slow execution speed # Lets say you're building cars. # A car can be split into several components, each described by a class. # i.e. Chassis, Wheels, Engine, Interior # At the toplevel, you would have the Car class, storing the other classes as it's attributes. # Here's an example class Chassis: CHASSIS_TYPE = ["Sedan", "Estate", "Pickup"] COLOR = ["Red", "Black", "Emerald"] def __init__(self, type="Sedan", col="Black"): self.type = type self.color = col class Wheels: RIM_TYPE = ["Steel rim", "Alloy rim"] TYRE_TYPE = ["R16/55 x 195", "R17/50 x 205", "R18/45 x 215", "R18/45 x 225", "R19/40 x 225", "R19/40 x 235"] def __init__(self, rim="Steel", tyre="R16/55 x 195"): self.rim = rim self.tyre = tyre class Engine: ENGINE_TYPE = ["Row", "V"] CYLINDER_COUNT = [4, 5, 6, 8] ENGINE_VOLUME = [1.4, 1.6, 1.8, 2.0, 3.0, 4.5] ENGINE_FUEL = ["Diesel", "Petrol", "Hydrogen", "Hybrid"] def __init__(self, type="Row", cyl=4, vol=1.4, fuel="Petrol"): self.type = type self.cylinder = cyl self.volume = vol self.fuel = fuel class Interior: INTERIOR_TYPE = ["Fabric", "Leather", "Vinyl"] STEERING_WHEEL = ["3-spoke bare", "2-spoke Leather"] def __init__(self, int="Fabric", steering="3-spoke bare"): self.interior = int self.steering_wheel = steering class Car: def __init__(self, type="Sedan", col="Black", rim="Steel rim", tyre="R16/55 x 195", engine="Row", cyl=4, vol=1.4, fuel="Petrol", int="Fabric", steering="3-spoke bare"): self.chassis = Chassis(type, col) self.wheels = Wheels(rim, tyre) self.engine = Engine(engine, cyl, vol, fuel) self.interior = Interior(int, steering) # Now we have the classes define with their default values. # So now we can create our Car() object like this. if __name__ == "__main__": mycar = Car() print(mycar.chassis.type) print(mycar.engine.type, str(mycar.engine.cylinder)+" Cylinder", str(mycar.engine.volume)+" Litre", mycar.engine.fuel) # Procedural Oriented Programming - POP # Computational steps are divided into separate modules containing grouped functions. # Computations will be done step by step, by calling these functions in turn. # Advantages # - General-purpose programming # - Code reusability # - Portable code # Disadvantages # - Hard to data protect # - Not suitable for real-world objects # - Harder to write # Example numbers = [1, 2, 3, 4] def sum_number_list(number_list) -> int|float: res = 0 for val in number_list: res += val return res print(sum_number_list(numbers)) # Function Programming # Everything is bind in pure mathematical functions style. # Functions are mathematical functions and statements are treated as # functional expression being executed to generate a value. # Lambda functions or recursion are usually used for implementation. # This is a 'what to solve' as opposed to 'how to solve' paradigm. # Advantages # - Simple to understand # - Easier debugging and testing # - Better comprehension and code readability # Disadvantages # - Low performance # - Writing programs is a masive task # - Harder to read code # Example import functools mylist = [11, 22, 33, 44] def sum_the_list(mylist): if len(mylist) == 1: return mylist[0] else: return mylist[0] + sum_the_list(mylist[1:]) print(functools.reduce(lambda x, y: x + y, mylist)) # You don't have to adhere to 1 specific paradigm. # They can be mixed in an application, and usually are.