Practice
Solution
Step 1: Trace the stack initialization
The CompositeIterator reverses children, so stack = [leafB, leafA].Step 2: Trace iteration order
Pop leafA first (stack now [leafB]), then leafB (stack empty). Names collected in order: 'A', then 'B'.Final Answer:
Option B -> Option BQuick Check:
Reversing children in stack causes correct iteration order [OK]
- Assuming original order without reversing stack
- Including composite node name in output
import copy
class Profile:
def __init__(self, name, scores):
self.name = name
self.scores = scores
def __deepcopy__(self, memo):
new_name = copy.deepcopy(self.name, memo)
new_scores = copy.deepcopy(self.scores, memo)
return Profile(new_name, new_scores)
original = Profile('Alice', [10, 20])
copy_obj = copy.deepcopy(original)
print('Original scores:', original.scores)
print('Copy scores:', copy_obj.scores)
copy_obj.scores.append(30)
print('After modifying copy scores:')
print('Original scores:', original.scores)
print('Copy scores:', copy_obj.scores)
Solution
Step 1: Trace initial print statements
Both original.scores and copy_obj.scores start as [10, 20], so first two prints show identical lists.Step 2: Trace modification and final prints
copy_obj.scores.append(30) modifies only the copy's scores list because deep copy created a new list. Original remains [10, 20]. Final prints reflect this separation.Final Answer:
Option B -> Option BQuick Check:
Deep copy prevents shared nested list -> original unchanged [OK]
- Assuming append affects original due to shared reference
Solution
Step 1: Understand the problem constraints
The instance must be lazily initialized and thread-safe, but synchronization overhead should be minimized.Step 2: Evaluate each approach
Synchronized method locks on every call, causing overhead. Eager initialization is thread-safe but not lazy. Unsynchronized static variable risks multiple instances in multithreaded contexts. Double-checked locking with volatile ensures lazy init, thread safety, and minimal locking.Final Answer:
Option D -> Option DQuick Check:
Double-checked locking balances thread safety and performance [OK]
- Assuming synchronized method is efficient enough
- Believing eager initialization is always best
- Ignoring volatile keyword necessity
Solution
Step 1: Recall Facade's purpose
Facade simplifies complex subsystems by providing a unified interface.Step 2: Analyze trade-offs
While Facade simplifies usage, it can hide advanced features, limiting flexibility.Step 3: Evaluate other options
A is incorrect because Facade reduces coupling by hiding subsystem details. C is incorrect; Facade's overhead is minimal. D is wrong; Facade does not require changing subsystems.Final Answer:
Option A -> Option A
- Believing Facade increases coupling instead of reducing it
- Assuming Facade adds heavy runtime overhead
- Thinking Facade requires modifying subsystems
Solution
Step 1: Analyze requirements
Control access by user roles -> Proxy fits. Add logging and caching without modifying code -> Decorator fits.Step 2: Evaluate options
A incorrectly assigns Facade for access control and Adapter for logging/caching. B misuses Adapter and Facade roles. C correctly assigns Proxy for access control and Decorator for adding behavior. D incorrectly uses Adapter for access control and Proxy for logging/caching.Final Answer:
Option C -> Option C
- Confusing Proxy and Decorator responsibilities
- Using Adapter or Facade for access control
- Assuming Proxy can add behavior like logging and caching
