Chapter 11: From Theory to Practice. Case Studies & Optimizations
Chapter 11: Practical Exercises of From Theory to Practice. Case Studies & Optimizations
The following exercises provide practical opportunities to delve into and enhance Python code for superior performance and efficiency. They cover a range of situations, including refining sorting algorithms, managing extensive datasets, and applying parallel processing techniques. These exercises are designed to mirror actual coding challenges you may encounter.
Exercise 1: Optimizing a Sorting Function
- Objective: Improve the performance of a Python sorting function.
- Task: Implement a custom sorting function and then optimize it using built-in Python functionalities.
Solution:
# Initial Custom Sorting Function
def custom_sort(arr):
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
return arr
# Optimized Sorting Using Built-in Sort
def optimized_sort(arr):
return sorted(arr)
# Example Usage
arr = [3, 1, 4, 1, 5, 9, 2, 6]
print("Custom Sort:", custom_sort(arr.copy()))
print("Optimized Sort:", optimized_sort(arr.copy()))
Exercise 2: Memory Optimization in Data Processing
- Objective: Optimize a Python function for memory usage.
- Task: Rewrite a function that processes a large dataset to be more memory-efficient using generators.
Solution:
# Initial Memory-Intensive Function
def process_data(data):
results = []
for item in data:
results.append(item * 2) # Some processing
return results
# Memory-Optimized Function Using Generators
def optimized_process_data(data):
for item in data:
yield item * 2
# Example Usage
large_data = range(1000000)
print("Memory-Optimized Processing:")
for result in optimized_process_data(large_data):
pass # Replace with actual use of 'result'
Exercise 3: Parallelizing a Computation-Intensive Task
- Objective: Use Python’s multiprocessing to optimize a computation-intensive task.
- Task: Modify a function that performs a CPU-bound operation to utilize multiple cores.
Solution:
from multiprocessing import Pool
def compute_square(n):
return n * n
def parallel_square(numbers):
with Pool(4) as pool:
return pool.map(compute_square, numbers)
# Example Usage
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("Parallel Square Computation:", parallel_square(numbers))
Exercise 4: Profiling and Optimizing Python Code
- Objective: Profile a Python script and identify bottlenecks.
- Task: Use
cProfile
to profile the given function and then optimize it.
Initial Function:
def find_primes(n):
primes = []
for num in range(2, n + 1):
prime = True
for i in range(2, num):
if (num % i) == 0:
prime = False
break
if prime:
primes.append(num)
return primes
# Profiling
import cProfile
cProfile.run('find_primes(1000)')
Optimized Function:
def optimized_find_primes(n):
primes = []
for num in range(2, n + 1):
if all(num % i != 0 for i in range(2, int(num**0.5) + 1)):
primes.append(num)
return primes
# Example Usage and Profiling
cProfile.run('optimized_find_primes(1000)')
Chapter 11: Practical Exercises of From Theory to Practice. Case Studies & Optimizations
The following exercises provide practical opportunities to delve into and enhance Python code for superior performance and efficiency. They cover a range of situations, including refining sorting algorithms, managing extensive datasets, and applying parallel processing techniques. These exercises are designed to mirror actual coding challenges you may encounter.
Exercise 1: Optimizing a Sorting Function
- Objective: Improve the performance of a Python sorting function.
- Task: Implement a custom sorting function and then optimize it using built-in Python functionalities.
Solution:
# Initial Custom Sorting Function
def custom_sort(arr):
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
return arr
# Optimized Sorting Using Built-in Sort
def optimized_sort(arr):
return sorted(arr)
# Example Usage
arr = [3, 1, 4, 1, 5, 9, 2, 6]
print("Custom Sort:", custom_sort(arr.copy()))
print("Optimized Sort:", optimized_sort(arr.copy()))
Exercise 2: Memory Optimization in Data Processing
- Objective: Optimize a Python function for memory usage.
- Task: Rewrite a function that processes a large dataset to be more memory-efficient using generators.
Solution:
# Initial Memory-Intensive Function
def process_data(data):
results = []
for item in data:
results.append(item * 2) # Some processing
return results
# Memory-Optimized Function Using Generators
def optimized_process_data(data):
for item in data:
yield item * 2
# Example Usage
large_data = range(1000000)
print("Memory-Optimized Processing:")
for result in optimized_process_data(large_data):
pass # Replace with actual use of 'result'
Exercise 3: Parallelizing a Computation-Intensive Task
- Objective: Use Python’s multiprocessing to optimize a computation-intensive task.
- Task: Modify a function that performs a CPU-bound operation to utilize multiple cores.
Solution:
from multiprocessing import Pool
def compute_square(n):
return n * n
def parallel_square(numbers):
with Pool(4) as pool:
return pool.map(compute_square, numbers)
# Example Usage
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("Parallel Square Computation:", parallel_square(numbers))
Exercise 4: Profiling and Optimizing Python Code
- Objective: Profile a Python script and identify bottlenecks.
- Task: Use
cProfile
to profile the given function and then optimize it.
Initial Function:
def find_primes(n):
primes = []
for num in range(2, n + 1):
prime = True
for i in range(2, num):
if (num % i) == 0:
prime = False
break
if prime:
primes.append(num)
return primes
# Profiling
import cProfile
cProfile.run('find_primes(1000)')
Optimized Function:
def optimized_find_primes(n):
primes = []
for num in range(2, n + 1):
if all(num % i != 0 for i in range(2, int(num**0.5) + 1)):
primes.append(num)
return primes
# Example Usage and Profiling
cProfile.run('optimized_find_primes(1000)')
Chapter 11: Practical Exercises of From Theory to Practice. Case Studies & Optimizations
The following exercises provide practical opportunities to delve into and enhance Python code for superior performance and efficiency. They cover a range of situations, including refining sorting algorithms, managing extensive datasets, and applying parallel processing techniques. These exercises are designed to mirror actual coding challenges you may encounter.
Exercise 1: Optimizing a Sorting Function
- Objective: Improve the performance of a Python sorting function.
- Task: Implement a custom sorting function and then optimize it using built-in Python functionalities.
Solution:
# Initial Custom Sorting Function
def custom_sort(arr):
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
return arr
# Optimized Sorting Using Built-in Sort
def optimized_sort(arr):
return sorted(arr)
# Example Usage
arr = [3, 1, 4, 1, 5, 9, 2, 6]
print("Custom Sort:", custom_sort(arr.copy()))
print("Optimized Sort:", optimized_sort(arr.copy()))
Exercise 2: Memory Optimization in Data Processing
- Objective: Optimize a Python function for memory usage.
- Task: Rewrite a function that processes a large dataset to be more memory-efficient using generators.
Solution:
# Initial Memory-Intensive Function
def process_data(data):
results = []
for item in data:
results.append(item * 2) # Some processing
return results
# Memory-Optimized Function Using Generators
def optimized_process_data(data):
for item in data:
yield item * 2
# Example Usage
large_data = range(1000000)
print("Memory-Optimized Processing:")
for result in optimized_process_data(large_data):
pass # Replace with actual use of 'result'
Exercise 3: Parallelizing a Computation-Intensive Task
- Objective: Use Python’s multiprocessing to optimize a computation-intensive task.
- Task: Modify a function that performs a CPU-bound operation to utilize multiple cores.
Solution:
from multiprocessing import Pool
def compute_square(n):
return n * n
def parallel_square(numbers):
with Pool(4) as pool:
return pool.map(compute_square, numbers)
# Example Usage
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("Parallel Square Computation:", parallel_square(numbers))
Exercise 4: Profiling and Optimizing Python Code
- Objective: Profile a Python script and identify bottlenecks.
- Task: Use
cProfile
to profile the given function and then optimize it.
Initial Function:
def find_primes(n):
primes = []
for num in range(2, n + 1):
prime = True
for i in range(2, num):
if (num % i) == 0:
prime = False
break
if prime:
primes.append(num)
return primes
# Profiling
import cProfile
cProfile.run('find_primes(1000)')
Optimized Function:
def optimized_find_primes(n):
primes = []
for num in range(2, n + 1):
if all(num % i != 0 for i in range(2, int(num**0.5) + 1)):
primes.append(num)
return primes
# Example Usage and Profiling
cProfile.run('optimized_find_primes(1000)')
Chapter 11: Practical Exercises of From Theory to Practice. Case Studies & Optimizations
The following exercises provide practical opportunities to delve into and enhance Python code for superior performance and efficiency. They cover a range of situations, including refining sorting algorithms, managing extensive datasets, and applying parallel processing techniques. These exercises are designed to mirror actual coding challenges you may encounter.
Exercise 1: Optimizing a Sorting Function
- Objective: Improve the performance of a Python sorting function.
- Task: Implement a custom sorting function and then optimize it using built-in Python functionalities.
Solution:
# Initial Custom Sorting Function
def custom_sort(arr):
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
return arr
# Optimized Sorting Using Built-in Sort
def optimized_sort(arr):
return sorted(arr)
# Example Usage
arr = [3, 1, 4, 1, 5, 9, 2, 6]
print("Custom Sort:", custom_sort(arr.copy()))
print("Optimized Sort:", optimized_sort(arr.copy()))
Exercise 2: Memory Optimization in Data Processing
- Objective: Optimize a Python function for memory usage.
- Task: Rewrite a function that processes a large dataset to be more memory-efficient using generators.
Solution:
# Initial Memory-Intensive Function
def process_data(data):
results = []
for item in data:
results.append(item * 2) # Some processing
return results
# Memory-Optimized Function Using Generators
def optimized_process_data(data):
for item in data:
yield item * 2
# Example Usage
large_data = range(1000000)
print("Memory-Optimized Processing:")
for result in optimized_process_data(large_data):
pass # Replace with actual use of 'result'
Exercise 3: Parallelizing a Computation-Intensive Task
- Objective: Use Python’s multiprocessing to optimize a computation-intensive task.
- Task: Modify a function that performs a CPU-bound operation to utilize multiple cores.
Solution:
from multiprocessing import Pool
def compute_square(n):
return n * n
def parallel_square(numbers):
with Pool(4) as pool:
return pool.map(compute_square, numbers)
# Example Usage
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("Parallel Square Computation:", parallel_square(numbers))
Exercise 4: Profiling and Optimizing Python Code
- Objective: Profile a Python script and identify bottlenecks.
- Task: Use
cProfile
to profile the given function and then optimize it.
Initial Function:
def find_primes(n):
primes = []
for num in range(2, n + 1):
prime = True
for i in range(2, num):
if (num % i) == 0:
prime = False
break
if prime:
primes.append(num)
return primes
# Profiling
import cProfile
cProfile.run('find_primes(1000)')
Optimized Function:
def optimized_find_primes(n):
primes = []
for num in range(2, n + 1):
if all(num % i != 0 for i in range(2, int(num**0.5) + 1)):
primes.append(num)
return primes
# Example Usage and Profiling
cProfile.run('optimized_find_primes(1000)')