How $\mathtt{assignment}$ and shared objects change the rules of reasoning
nonlocaldef make_withdraw(balance):
"""Return a withdraw function with private, mutable balance."""
def withdraw(amount):
nonlocal balance
if amount <= balance:
balance -= amount
return balance
return "Insufficient funds"
return withdraw
if __name__ == "__main__":
wd = make_withdraw(100)
print(wd(25))
print(wd(25))
print(wd(60))
print(wd(15))
nonlocal balance = rebind the name in the enclosing framewd(25) can yield different results over timemake_withdraw: binds balancewithdraw closes over that framebalance: 100 → 75 → 50 → 50 → 35 (the 60 withdrawal fails, so no change)def make_account(balance):
"""Return a dispatch function for a bank account with private balance."""
def withdraw(amount):
nonlocal balance
if amount <= balance:
balance -= amount
return balance
return "Insufficient funds"
def deposit(amount):
nonlocal balance
balance += amount
return balance
def dispatch(message):
if message == "withdraw":
return withdraw
if message == "deposit":
return deposit
raise ValueError(f"Unknown request: {message}")
return dispatch
if __name__ == "__main__":
acc = make_account(100)
print(acc("deposit")(50))
print(acc("withdraw")(30))
acc("deposit")(50) and acc("withdraw")(30)balance directlydef list_mutation_demo():
lst = [3, 1, 2]
lst.append(4) # in-place
lst.extend([9, 8]) # in-place
last = lst.pop() # removes and returns
lst.sort() # in-place sort
return lst, last
if __name__ == "__main__":
print(list_mutation_demo())
append, extend, pop, sortlast be, and what will lst be at the end?def aliasing_demo():
a = [1, 2, 3]
b = a # aliasing: b and a refer to the same list
b.append(4)
return a, bdef nested_aliasing_demo():
a = [1, 2]
b = [a, a] # the same list appears twice
a.append(3)
return bif __name__ == "__main__":
print(aliasing_demo())
print(nested_aliasing_demo())[a, a] duplicates a reference, not a copydef identity_vs_equality():
x = [1, 2]
y = [1, 2]
a = x
return {
"x == y": (x == y),
"x is y": (x is y),
"x is a": (x is a),
}def append_bad(item, bucket=[]):
bucket.append(item)
return bucketdef append_good(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucketif __name__ == "__main__":
print(identity_vs_equality())
print(append_bad(1))
print(append_bad(2))
print(append_good(1))
print(append_good(2))== compares contents; is compares identity (same object)a=[0]; b=[a,a]; b[0].append(1); print(b)
Powered by SciMigo AI Tutor - https://scimigo.com