Practice reasoning about time-varying state: mutation vs rebinding, closures with nonlocal state, aliasing, identity vs equality, and the mutable-default-argument trap.
**Predict the result** before running.
This function has a mutable default argument:
```python
def append_bad(item, bucket=[]):
bucket.append(item)
return bucket
def demo():
a = append_bad(1)
b = append_bad(2)
fresh = append_bad(3, [])
return a, b, (a is b), fresh
```
1) What does `demo()` return?
2) Why is `(a is b)` either `True` or `False`?
After you write your prediction, run the code to check.This closure uses `nonlocal` to update a private `balance` over time.
```python
def make_withdraw(balance):
def withdraw(amount):
nonlocal balance
if amount <= balance:
balance -= amount
return balance
return "Insufficient funds"
return withdraw
```
**Trace** `run()` by writing (in comments) what `balance` is after each call, and what each call returns.
Focus questions:
- Which frame stores `balance`?
- Does a failed withdrawal change `balance`?
Then run to confirm.Modify message-passing bank accounts to require a password.
Implement `make_account(balance, password)` so that:
- `acc(correct_pw, "withdraw")` returns a **function** that withdraws.
- `acc(correct_pw, "deposit")` returns a **function** that deposits.
- Any request with a wrong password returns the string **"Incorrect password"** (not a function).
**Predict (before running)** what each line should evaluate to:
```python
acc = make_account(100, "secret")
acc("secret", "deposit")(50) # ?
acc("secret", "withdraw")(30) # ?
acc("wrong", "withdraw") # ?
```
Then implement and run the tests.