Identity vs.Equality in Environment Diagrams ● Review:For assignment statements,evaluate the right side,then assign to the left. ● Copying:When creating a copy,copy exactly what's "in the box". Global frame list 0 Ist1 -2 >>1st1=[0,6,[-2,4]] Ist2 Ist3 s式 >>>1st2=1st1 0 0 >>>1st3=1st1[1:] ist 6
Identity vs. Equality in Environment Diagrams ● Review: For assignment statements, evaluate the right side, then assign to the left. ● Copying: When creating a copy, copy exactly what’s “in the box”. >>> lst1 = [0, 6, [-2, 4]] >>> lst2 = lst1 >>> lst3 = lst1[1:]
Mutating Within Functions >>> def mystery(1st):mutative function 1st.pop() 1st.pop() >>> four=[4,4,4,4] >>mystery(four)) >>four [4,4]
Mutating Within Functions >>> def mystery(lst): # mutative function ... lst.pop() ... lst.pop() >>> four = [4, 4, 4, 4] >>> mystery(four) >>> four [4, 4]
Functions with behavior that changes over time def square(x): def f(x): return xx >>square(5) Returns the same >>>f(5) 25 value when called with 25 the same input >>square(5) >>f(5) 25 Return values are 26 >>square(5) different when called >f(5) 25 with the same input 27
Functions with behavior that changes over time 6 def square(x): return x * x >>> square(5) 25 >>> square(5) 25 >>> square(5) 25 def f(x): ... >>> f(5) 25 >>> f(5) 26 >>> f(5) 27 Returns the same value when called with the same input Return values are different when called with the same input
Example-Withdraw Let's model a bank account that has a balance of $100 Argument: Return value: >>withdraw(25) amount to withdraw remaining balance 75 >>withdraw(25) Second withdrawal of the same Different amount return value! 50 >>withdraw(60) Where's this balance stored? 'Insufficient funds' Within the parent frame of the function! >>withdraw(15) 35 A function has a body and a parent >>withdraw environment
Example - Withdraw >>> withdraw(25) 75 >>> withdraw(25) 50 >>> withdraw(60) 'Insufficient funds' >>> withdraw(15) 35 >>> withdraw = make_withdraw(100) Let's model a bank account that has a balance of $100 Argument: amount to withdraw Return value: remaining balance Different return value! Where's this balance stored? 7 Second withdrawal of the same amount A function has a body and a parent environment Within the parent frame of the function!
Persistent Local State Using Environments Global frame >func make_withdraw(balance)[parent=Global] make_withdraw func withdraw(amount)[parent=f1] withdraw f1:make_withdraw [parent=Global] balance 50 withdraw The parent frame contains the balance,the local state Return of the withdraw function value f2:withdraw [parent=f1] All calls to the same amount 25 Every call decreases the same balance by function have the Return value 75 (a possibly different)amount same parent f3:withdraw [parent=f1] amount 25 Return value 50
Persistent Local State Using Environments The parent frame contains the balance, the local state of the withdraw function Every call decreases the same balance by (a possibly different) amount 8 All calls to the same function have the same parent
Reminder:Local Assignment def percent_difference(x.y): difference abs(x-y) return i00+difference /x Assignment binds name(s)to value(s) in the first frame of the current diff percent difference(40.50) environment Global frame >func percent_difference(x.y)[parent=Global] percent_difference f1:percent_difference [parent=Global] ×40 y50 difference 10 Execution rule for assignment statements: 1.Evaluate all expressions right of =from left to right 2.Bind the names on the left to the resulting values in the current frame
Reminder: Local Assignment Execution rule for assignment statements: 1. Evaluate all expressions right of =, from left to right 2. Bind the names on the left to the resulting values in the current frame Assignment binds name(s) to value(s) in the first frame of the current environment 9
Non-Local Assignment Persistent Local State Demo def make_withdraw(balance): """Return a withdraw function with a starting balance.""" def withdraw(amount): Declare the name "balance"nonlocal at the top of the nonlocal balance body of the function in which it is re-assigned if amount balance: return Insufficient funds' balancebalance amount Re-bind balance in the first non-local frame in which it was bound previously return balance return withdraw
Non-Local Assignment & Persistent Local State def make_withdraw(balance): """Return a withdraw function with a starting balance.""" def withdraw(amount): nonlocal balance if amount > balance: return 'Insufficient funds' balance = balance - amount return balance return withdraw Declare the name "balance" nonlocal at the top of the body of the function in which it is re-assigned Re-bind balance in the first non-local frame in which it was bound previously 10 Demo