Predict outputs, trace dispatch (attribute lookup + data-directed tables), then implement and extend a tiny generic-operation system inspired by SICP.
**Predict what will be printed** (write your prediction as a comment *before* running).
Focus question: when `withdraw` uses `self.withdrawal_fee`, will it use the class attribute or the instance attribute?
```python
class Account:
def __init__(self, holder, balance=0):
self.holder = holder
self.balance = balance
def withdraw(self, amount):
if amount > self.balance:
return 'Insufficient funds'
self.balance -= amount
return self.balance
class CheckingAccount(Account):
withdrawal_fee = 1
def withdraw(self, amount):
return super().withdraw(amount + self.withdrawal_fee)
ch = CheckingAccount('Eve', 10)
ch.withdrawal_fee = 5
ch.withdraw(3)
print(ch.balance)
```
What does it print?This is a tiny data-directed dispatch system.
`z` is tagged as `'complex'`, but inside it stores another tagged value (like `'rect'`).
**Task (trace, by hand):** When evaluating `magnitude(z)`,
1) How many times is `apply_generic` invoked?
2) What type-tag(s) does it see each time?
3) Which function does it dispatch to each time?
Then run to verify it returns `5.0`.
```python
import math
def attach_tag(tag, contents):
return (tag, contents)
def type_tag(d):
return d[0]
def contents(d):
return d[1]
_op = {}
def put(op, tags, fn):
_op[(op, tuple(tags))] = fn
def get(op, tags):
return _op.get((op, tuple(tags)))
def apply_generic(op, x):
fn = get(op, [type_tag(x)])
return fn(contents(x))
def magnitude(z):
return apply_generic('magnitude', z)
# rect package
put('magnitude', ['rect'], lambda xy: math.hypot(xy[0], xy[1]))
# complex package (wrapper delegates to inner tagged value)
put('magnitude', ['complex'], lambda inner_tagged: magnitude(inner_tagged))
z = attach_tag('complex', attach_tag('rect', (3.0, 4.0)))
print(magnitude(z))
```You are given a tiny generic-operation table and two complex representations: `'rect'` and `'polar'`.
Your job:
**Part A (implement):** Install generic equality `equ(z1, z2)` for same-type comparisons:
- `('num','num')`
- `('rect','rect')`
- `('polar','polar')`
**Part B (extend):** Without changing `equ` itself, add *cross-type* comparisons so these also work:
- `('rect','polar')` and `('polar','rect')`
Rule: two complex numbers are equal if both their real parts and imaginary parts are close (use `math.isclose` with `abs_tol=1e-9`).
Before running, predict:
- Should `equ(z_rect, z_polar)` be `True` for the two representations of 3+4i below?
Then run the tests.