1"""
2Programming Paradigm Comparison
3
4Problem: Given a list of numbers, filter out negatives, square the positives,
5and return the sum of squares.
6
7This demonstrates the same problem solved using:
81. Imperative Programming (step-by-step instructions)
92. Object-Oriented Programming (data + behavior encapsulation)
103. Functional Programming (pure functions + composition)
11"""
12
13from typing import List
14from functools import reduce
15
16
17# =============================================================================
18# 1. IMPERATIVE STYLE: Focus on HOW to do it (step-by-step)
19# =============================================================================
20
21def imperative_approach(numbers: List[int]) -> int:
22 """
23 Imperative style uses explicit loops and mutable state.
24 We tell the computer exactly WHAT to do at each step.
25 """
26 # Step 1: Create mutable accumulator
27 result = 0
28
29 # Step 2: Iterate through each number
30 for num in numbers:
31 # Step 3: Check condition
32 if num > 0:
33 # Step 4: Transform (square)
34 squared = num * num
35 # Step 5: Accumulate
36 result += squared
37
38 return result
39
40
41# =============================================================================
42# 2. OBJECT-ORIENTED STYLE: Focus on objects with data + behavior
43# =============================================================================
44
45class NumberProcessor:
46 """
47 OOP encapsulates data and operations together.
48 State is managed within the object.
49 """
50
51 def __init__(self, numbers: List[int]):
52 self._numbers = numbers
53 self._filtered = []
54 self._squared = []
55 self._sum = 0
56
57 def filter_positives(self) -> 'NumberProcessor':
58 """Remove negative numbers (method chaining support)"""
59 self._filtered = [n for n in self._numbers if n > 0]
60 return self
61
62 def square_values(self) -> 'NumberProcessor':
63 """Square each value"""
64 self._squared = [n * n for n in self._filtered]
65 return self
66
67 def calculate_sum(self) -> 'NumberProcessor':
68 """Calculate sum of all values"""
69 self._sum = sum(self._squared)
70 return self
71
72 def get_result(self) -> int:
73 """Return final result"""
74 return self._sum
75
76
77def oop_approach(numbers: List[int]) -> int:
78 """
79 OOP style uses objects to encapsulate state and behavior.
80 Supports method chaining for fluent interface.
81 """
82 processor = NumberProcessor(numbers)
83 return (processor
84 .filter_positives()
85 .square_values()
86 .calculate_sum()
87 .get_result())
88
89
90# =============================================================================
91# 3. FUNCTIONAL STYLE: Focus on WHAT to compute (composition of functions)
92# =============================================================================
93
94def is_positive(n: int) -> bool:
95 """Pure function: same input always returns same output"""
96 return n > 0
97
98
99def square(n: int) -> int:
100 """Pure function: no side effects"""
101 return n * n
102
103
104def add(a: int, b: int) -> int:
105 """Pure function for reduction"""
106 return a + b
107
108
109def functional_approach(numbers: List[int]) -> int:
110 """
111 Functional style uses pure functions and function composition.
112 No mutable state, no side effects.
113 Data flows through transformations.
114 """
115 return reduce(
116 add,
117 map(square, filter(is_positive, numbers)),
118 0 # initial value
119 )
120
121
122def functional_approach_comprehension(numbers: List[int]) -> int:
123 """
124 Alternative functional style using list comprehension
125 (more Pythonic, still functionally pure)
126 """
127 return sum(n * n for n in numbers if n > 0)
128
129
130# =============================================================================
131# COMPARISON & DEMONSTRATION
132# =============================================================================
133
134def compare_paradigms():
135 """Compare all three paradigms with the same input"""
136
137 test_data = [-5, 3, -2, 8, 0, 4, -1, 6]
138
139 print("=" * 70)
140 print("PROGRAMMING PARADIGM COMPARISON")
141 print("=" * 70)
142 print(f"\nInput: {test_data}")
143 print(f"Task: Filter positives → Square → Sum\n")
144
145 # Test all approaches
146 imperative_result = imperative_approach(test_data)
147 oop_result = oop_approach(test_data)
148 functional_result = functional_approach(test_data)
149 functional_comp_result = functional_approach_comprehension(test_data)
150
151 print("RESULTS:")
152 print(f" Imperative: {imperative_result}")
153 print(f" Object-Oriented: {oop_result}")
154 print(f" Functional: {functional_result}")
155 print(f" Functional (comp): {functional_comp_result}")
156
157 # Verify all give same result
158 assert imperative_result == oop_result == functional_result == functional_comp_result
159 print("\n✓ All paradigms produce identical results!\n")
160
161 # Show step-by-step breakdown
162 print("STEP-BY-STEP BREAKDOWN:")
163 positives = [n for n in test_data if n > 0]
164 print(f" 1. Filter positives: {positives}")
165 squares = [n * n for n in positives]
166 print(f" 2. Square values: {squares}")
167 total = sum(squares)
168 print(f" 3. Sum: {total}")
169
170 print("\n" + "=" * 70)
171 print("PARADIGM CHARACTERISTICS")
172 print("=" * 70)
173
174 print("\nIMPERATIVE:")
175 print(" ✓ Explicit control flow (loops, conditionals)")
176 print(" ✓ Mutable state (variables change)")
177 print(" ✓ Step-by-step instructions")
178 print(" ✓ Easy to debug (can inspect each step)")
179 print(" ✗ More verbose")
180 print(" ✗ Harder to parallelize")
181
182 print("\nOBJECT-ORIENTED:")
183 print(" ✓ Encapsulation (data + behavior together)")
184 print(" ✓ Reusable objects")
185 print(" ✓ Method chaining (fluent interface)")
186 print(" ✓ Good for complex state management")
187 print(" ✗ Can be over-engineered for simple tasks")
188 print(" ✗ Mutable state can lead to bugs")
189
190 print("\nFUNCTIONAL:")
191 print(" ✓ Pure functions (no side effects)")
192 print(" ✓ Immutable data")
193 print(" ✓ Function composition")
194 print(" ✓ Easy to test and parallelize")
195 print(" ✓ Declarative (what, not how)")
196 print(" ✗ Can be less intuitive initially")
197 print(" ✗ May use more memory (creates new data)")
198
199 print("\n" + "=" * 70)
200 print("WHEN TO USE EACH PARADIGM")
201 print("=" * 70)
202
203 print("\nIMPERATIVE:")
204 print(" • Performance-critical code")
205 print(" • Systems programming")
206 print(" • When you need fine-grained control")
207
208 print("\nOBJECT-ORIENTED:")
209 print(" • Complex state management")
210 print(" • Modeling real-world entities")
211 print(" • Large codebases with multiple developers")
212 print(" • GUI applications")
213
214 print("\nFUNCTIONAL:")
215 print(" • Data transformation pipelines")
216 print(" • Concurrent/parallel processing")
217 print(" • Mathematical computations")
218 print(" • When immutability is important")
219
220
221def demonstrate_hybrid_approach():
222 """
223 Modern programming often uses a HYBRID approach,
224 combining the best of all paradigms.
225 """
226 print("\n" + "=" * 70)
227 print("HYBRID APPROACH (Real-world Python)")
228 print("=" * 70)
229
230 class DataPipeline:
231 """OOP structure with functional transformations"""
232
233 def __init__(self, data: List[int]):
234 self.data = data
235
236 def process(self) -> int:
237 """Functional operations within OOP structure"""
238 return sum(n * n for n in self.data if n > 0)
239
240 test_data = [-5, 3, -2, 8, 0, 4]
241 pipeline = DataPipeline(test_data)
242 result = pipeline.process()
243
244 print(f"\nInput: {test_data}")
245 print(f"Result: {result}")
246 print("\nThis combines:")
247 print(" • OOP: Class structure for organization")
248 print(" • Functional: Pure transformation with comprehension")
249 print(" • Imperative: Hidden in Python's built-in functions")
250 print("\nMost modern code uses this pragmatic mix!")
251
252
253if __name__ == "__main__":
254 compare_paradigms()
255 demonstrate_hybrid_approach()
256
257 print("\n" + "=" * 70)
258 print("KEY TAKEAWAY")
259 print("=" * 70)
260 print("""
261Paradigms are TOOLS, not religions.
262Choose based on the problem:
263 • Imperative for control and performance
264 • OOP for modeling and state management
265 • Functional for transformations and safety
266 • Hybrid for real-world pragmatism
267""")