Practice
Solution
Step 1: Understand naive search
MRO does not simply search the first parent class fully before moving to the next; it uses a more sophisticated approach.Step 2: Recognize MRO linearization
MRO uses a specific linearization (like C3 linearization) that merges parent classes and their ancestors in a consistent order.Step 3: Eliminate incorrect options
MRO always calls the method from the last parent class listed in the inheritance is incorrect because the last parent is not always chosen; order and ancestors matter. MRO randomly picks the method from any parent class that defines it is incorrect because MRO is deterministic, not random.Final Answer:
Option A -> Option AQuick Check:
MRO merges inheritance hierarchies to find the correct method in a predictable order.
- Assuming simple left-to-right search suffices
- Believing last parent always overrides
- Thinking method choice is random
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
class CreditCardStrategy(PaymentStrategy):
def pay(self, amount):
print(f"Processing credit card payment of ${amount}")
class UPIStrategy(PaymentStrategy):
def pay(self, amount):
print(f"Processing UPI payment of ${amount}")
class PaymentStrategyFactory:
@staticmethod
def get_strategy(method):
if method == 'CreditCard':
return CreditCardStrategy()
elif method == 'UPI':
return UPIStrategy()
else:
raise ValueError('Invalid payment method')
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self.strategy = strategy
def pay(self, amount):
self.strategy.pay(amount)
processor = PaymentProcessor(PaymentStrategyFactory.get_strategy('UPI'))
processor.pay(100)
Solution
Step 1: Trace strategy selection
The factory methodget_strategy('UPI')returns an instance ofUPIStrategy.Step 2: Trace payment method call
Thepaymethod ofUPIStrategyprints "Processing UPI payment of $100".Final Answer:
Option D -> Option DQuick Check:
Correct strategy instance leads to correct output [OK]
- Confusing strategy returned or output string
Solution
Step 1: Analyze statement A
OCP does not forbid all modifications; it encourages minimizing changes to stable, tested code but allows modifications when necessary.Step 2: Validate other statements
Statements B, C, and D correctly describe OCP's goals and mechanisms.Step 3: Why A is incorrect
Absolute prohibition of modification is impractical; OCP is about minimizing and isolating changes.Final Answer:
Option A -> Option AQuick Check:
OCP is about minimizing, not forbidding, modifications.
- Interpreting OCP as no code changes ever allowed
- Ignoring the role of abstraction in OCP
- Underestimating OCP's impact on bug reduction
import copy
class Profile:
def __init__(self, name, scores):
self.name = name
self.scores = scores
def __deepcopy__(self, memo):
new_name = self.name # Bug here
new_scores = copy.deepcopy(self.scores, memo)
return Profile(new_name, new_scores)
original = Profile('Alice', [10, 20])
copy_obj = copy.deepcopy(original)
copy_obj.scores.append(30)
print(original.scores)
Solution
Step 1: Examine __deepcopy__ method
The line new_name = self.name copies the reference to the name string instead of deep copying it.Step 2: Understand impact
Strings are immutable in Python, so shallow copy is usually safe, but if name were a mutable object, this would cause shared references and bugs. Proper deep copy should be used for consistency.Final Answer:
Option A -> Option AQuick Check:
Only new_name assignment lacks deepcopy -> subtle bug [OK]
- Forgetting to deepcopy all nested fields, assuming immutables are safe
Solution
Step 1: Understand reuse implications
Reusing the same command instance for multiple executions causes undo/redo to affect the wrong state because the command's internal state may change.Step 2: Identify correct approach
Creating a new command instance per execution ensures each undo/redo corresponds to the exact executed command instance and its parameters.Step 3: Confirm undo/redo stack integrity
This approach preserves correct ordering and state consistency during undo/redo operations.Final Answer:
Option C -> Option CQuick Check:
New instances per execution prevent state corruption on undo/redo [OK]
- Reusing command instances causing incorrect undos
- Clearing stacks unnecessarily losing history
