Chapter 7B - Passing Immutable & Mutable Objects?
Chapter 7B - Passing Immutable & Mutable Objects?
Slides prepared by - Dr. Chui Chun Kit (http://www.cs.hku.hk/~ckchui/) and Dr. Dirk Schnieders for students in ENGG1330. For other uses, please email : [email protected]
Mutable and immutable
Objects of built-in types like (int, float, bool, str, tuple) are immutable.
Objects of built-in types like (list, set, dict) are mutable.
To understand this
Confusion: I would like
concept, we need to be
to make it clear about
clear about what are:
what is mutable and
1. Variable
immutable!
2. Object
3. Value
4. Reference
Variable, object, value and reference?
1
a = 10 2
This is a variable named a . This is an int object with value 10.
a 10
3
With the = sign, the variable a references to an
int object, that has a value 10.
int objects are immutable?
Answer Question
By int objects are
immutable, we say
The int object with value
a = 10 But we say int objects are
immutable, why the value of
variable a can be changed?
10 cannot be changed.
With a=20, another int
object with value 20 is
a = 20
created, and the variable a
a
int objects are
is updated to reference to it!
10 immutable
(These int objects
won’t be updated.
However, the
20 reference to these
objects are
updated.)
Variable, object, value and reference?
1
a = "Kit" 2
A variable named a A str object with value "Kit"
a Kit
3
With the = sign, the variable a reference to a
str object, that has a value "Kit".
str is immutable
a = "Kit"
Similar to int, str objects are
immutable. So a="Kitty" is
NOT changing "Kit", the
"Kit" str object is still there.
In fact, a new str object
"Kitty" is created, and a’s
a = "Kitty"
reference is updated to
refer to "Kitty".
a Kit str objects are Immutable
(These str objects won’t be
updated. However, the
def main():
n=1
print("n",id(n),n)
n 1460101344 1
n 1
n=2
print("n",id(n),n)
m=n
print("m",id(m),m)
m=3
print("m",id(m),m)
print("n",id(n),n)
main()
Example 1. Verify int immutability
1460101344
def main():
n=1
print("n",id(n),n)
n 1460101344 1
n 1460101376 2
n 1
1460101376
n=2
print("n",id(n),n)
m=n
print("m",id(m),m)
2
m=3
print("m",id(m),m)
print("n",id(n),n)
main()
Example 1. Verify int immutability
Note: Depending on the Python’s implementation, both m and n can
be referencing the same int object with value 2, or it is also possible to
have m and n referencing to different int objects, both with value 2.
1460101344
def main():
n=1
print("n",id(n),n)
n 1460101344 1
n 1460101376 2
n 1
1460101376
n=2 m 1460101376 2
print("n",id(n),n)
m=n
print("m",id(m),m)
m=3
m 2
print("m",id(m),m)
print("n",id(n),n)
main()
Example 1. Verify int immutability
1460101344
def main():
n=1
print("n",id(n),n)
n 1460101344 1
n 1460101376 2
n 1
1460101376
n=2 m 1460101376 2
print("n",id(n),n)
m=n
print("m",id(m),m)
m=3
m 1460101408 3
n 1460101376 2 m 2
1460101408
print("m",id(m),m)
print("n",id(n),n)
main() 3
Example 2. Verify str immutability
2163071741432
def main():
a="Kit"
print("a",id(a),a)
b="Kit"
a 2163071741432 Kit
a Kit
print("b",id(b),b)
b="Kitty"
print("b",id(b),b)
a="Kitty"
print("a",id(a),a)
a=a+b
print("a",id(a),a)
main()
Example 2. Verify str immutability
2163071741432
def main():
a="Kit"
print("a",id(a),a)
b="Kit"
a 2163071741432 Kit
b 2163071741432 Kit a Kit
print("b",id(b),b)
b="Kitty"
print("b",id(b),b)
a="Kitty"
b
print("a",id(a),a)
a=a+b
print("a",id(a),a)
main()
Example 2. Verify str immutability
2163071741432
def main():
a="Kit"
print("a",id(a),a)
b="Kit"
a 2163071741432 Kit
b 2163071741432 Kit
b 2163071840864 Kitty
a Kit
2163071840864
print("b",id(b),b)
b="Kitty"
print("b",id(b),b)
a="Kitty"
b Kitty
print("a",id(a),a)
a=a+b
print("a",id(a),a)
main()
Example 2. Verify str immutability
2163071741432
def main():
a="Kit"
print("a",id(a),a)
b="Kit"
a 2163071741432 Kit
b 2163071741432 Kit
b 2163071840864 Kitty
a Kit
2163071840864
b
print("b",id(b),b) a 2163071840864 Kitty
b="Kitty"
print("b",id(b),b)
Kitty
a="Kitty"
print("a",id(a),a)
main()
Example 2. Verify str immutability
2163071741432
def main():
a="Kit"
print("a",id(a),a)
b="Kit"
a 2163071741432 Kit
b 2163071741432 Kit
b 2163071840864 Kitty
a Kit
2163071840864
b
print("b",id(b),b) a 2163071840864 Kitty
b="Kitty"
print("b",id(b),b)
a 2163071803760 KittyKitty Kitty
a="Kitty"
print("a",id(a),a) 2163071803760
First, the operator + will concatenate
a=a+b
print("a",id(a),a)
main()
str a and str b and create a new str
object "KittyKitty". KittyKitty
Then the operator = will update
variable a’s reference to the new str
object "KittyKitty".
list objects are mutable
(list stores a number of references
Example 3. Verify list mutability to other objects, these references
can be updated.)
1890234032456
def main():
a
a 1890234032456 [1, 2, 3]
a=[1,2,3]
print("a",id(a),a)
a[0]=4
[ , , ]
1 2 3
print("a",id(a),a)
int objects are immutable
(int objects won’t be updated. However the
reference to these objects can be updated.)
main()
Example 3. Verify list mutability
1890234032456
def main():
a
a 1890234032456 [1, 2, 3]
a=[1,2,3]
print("a",id(a),a)
a[0]=4
a 1890234032456 [4, 2, 3]
[ , , ]
print("a",id(a),a)
b=a
print("b",id(b),b)
b[2]=5
print("a",id(a),a)
4 1 2 3
print("b",id(b),b) Because list objects are mutable, it
means the content of the list (i.e., in
this example the references to the
main() int objects) can be updated.
Therefore, we can have a[0]=4.
We cannot do it if a is a tuple.
Example 3. Verify list mutability
1890234032456
def main():
a
a 1890234032456 [1, 2, 3]
a=[1,2,3]
print("a",id(a),a)
a[0]=4
a 1890234032456 [4, 2, 3]
b 1890234032456 [4, 2, 3] [ , , ]
print("a",id(a),a)
b=a
print("b",id(b),b)
b[2]=5
print("a",id(a),a)
4 1 2 3
print("b",id(b),b)
b
With b=a, we are updating b to reference to the
main()
list that is currently referenced by a.
Therefore the id()s of both a and b are the same.
Example 3. Verify list mutability
1890234032456
def main():
a
a 1890234032456 [1, 2, 3]
a=[1,2,3]
print("a",id(a),a)
a[0]=4
a 1890234032456 [4, 2, 3]
b 1890234032456 [4, 2, 3]
a 1890234032456 [4, 2, 5]
[ , , ]
b 1890234032456 [4, 2, 5]
print("a",id(a),a)
b=a
print("b",id(b),b)
b[2]=5
print("a",id(a),a)
4 1 2 3 5
print("b",id(b),b)
b
Because both a and b are referencing to the
main()
same list object, updating list b essentially
means updating list a.
Example 3. Verify list mutability
1890234032456
def main():
a
a 1890234032456 [1, 2, 3]
a=[1,2,3]
print("a",id(a),a)
a[0]=4
a 1890234032456 [4, 2, 3]
b 1890234032456 [4, 2, 3]
a 1890234032456 [4, 2, 5]
[ , , ]
b 1890234032456 [4, 2, 5]
print("a",id(a),a)
a 1890234032456 [4, 2, 5]
b=a
print("b",id(b),b)
b[2]=5
print("a",id(a),a)
b 1890234060220 [4, 2, 5]
4 1 2 3 5
At this moment, 1890234060220
print("b",id(b),b)
b=[4,2,5]
print("a",id(a),a)
print("b",id(b),b)
although the values of
both list a and list b
are the same, but
b [ , , ]
main() they are two different
list objects. 4 2 5
Example 4. Verify tuple immutability
def main(): a 2478472831840 (1, 2, 3) 2478472831840
a=(1,2,3)
print("a",id(a),a)
main()
a ( , , )
tuple objects are immutable
(tuple stores a number of
references to other objects, these
references CANNOT be updated.)
1 2 3
Example 4. Verify tuple immutability
def main(): a 2478472831840 (1, 2, 3) 2478472831840
a
a=(1,2,3) Traceback (most recent call last):
print("a",id(a),a)
a[0]=4
…
TypeError: 'tuple' object does
not support item assignment
( , , )
main()
1 2 3
There is NO in-place update of tuple
object because tuple is immutable!
Passing immutable objects in function
def update(n): In main(): n before update 1704999312 10
print("In update(): n before +=",id(n),n)
n+=20
print("In update(): n after +=",id(n),n)
def main():
n=10
print("In main(): n before update",id(n),n)
update(n)
print("In main(): n after update",id(n),n)
main()
main()
1704999312
n 10
Passing immutable objects in function
def update(n): In main(): n before update 1704999312 10
print("In update(): n before +=",id(n),n) In update(): n before += 1704999312 10
n+=20
print("In update(): n after +=",id(n),n)
In chapter 7A, we learned that
def main(): the variable n in update() and the
n=10
print("In main(): n before update",id(n),n) variable n in main() are different
update(n) variables! They are local variables
print("In main(): n after update",id(n),n) to their functions.
main() They both reference to the same
object in the function call.
main() update()
1704999312
n 10 n
Passing immutable objects in function
def update(n): In main(): n before update 1704999312 10
print("In update(): n before +=",id(n),n) In update(): n before += 1704999312 10
n+=20 In update(): n after += 1704999888 30
print("In update(): n after +=",id(n),n)
def main():
n=10 Now n in update() references to
print("In main(): n before update",id(n),n) another new int object!
update(n)
print("In main(): n after update",id(n),n)
The key point lies in the += operator.
The += operator creates a new int
main() object and update n’s reference
main() update()
1704999312 1704999888
n 10 n 30
Passing immutable objects in function
def update(n): In main(): n before update 1704999312 10
print("In update(): n before +=",id(n),n) In update(): n before += 1704999312 10
n+=20 In update(): n after += 1704999888 30
print("In update(): n after +=",id(n),n) In main(): n after update 1704999312 10
def main():
n=10 This is why if we update immutable
print("In main(): n before update",id(n),n) input argument in function, the
update(n)
print("In main(): n after update",id(n),n) original variable will NOT be updated!
If we wish to update n in main(), We
main()
can use return statement instead.
main() update()
1704999312 1704999888
n 10 n 30
Example 5 Clear concept: With the same
concept, I can now explain
def salary_adjust (sal): why this code won’t update
sal = sal * 1.05
the salary variable in
def main(): main() function
salary = 20000;
print("The original salary is" , salary)
salary_adjust(salary)
print("The new salary is" ,salary )
main()
The original salary is 20000
Example 5
def salary_adjust (sal):
sal = sal * 1.05
def main():
salary = 20000;
print("The original salary is" , salary)
salary_adjust(salary)
print("The new salary is" ,salary )
main()
main()
int objects are immutable
main() salary_adjust()
main()
main() salary_adjust()
main() salary_adjust()
salary 20000
The original salary is 20000
Example 6
def salary_adjust (sal):
sal = sal * 1.05
return sal
def main():
salary = 20000;
print("The original salary is " , salary)
salary = salary_adjust(salary)
print("The new salary is " ,salary )
main()
main() salary_adjust()
def main():
salary = 20000;
print("The original salary is " , salary)
salary = salary_adjust(salary)
print("The new salary is " ,salary )
main()
main() salary_adjust()
def main():
salary = 20000;
print("The original salary is " , salary)
salary = salary_adjust(salary)
print("The new salary is " ,salary )
main()
main()
main()
main()
salary 21000.0
Passing mutable objects in function
Mutable list object
def update(n):
(list objects can be updated, in fact, the reference stored in each
print(id(n),n)
slot of the list can be updated to refer to other objects.)
n.append(3)
print(id(n),n) main() 57060408
def main():
n=[1,2]
print(id(n),n)
update(n)
n [ , ]
print(id(n),n)
main()
1 2
57060408 [1, 2]
main()
1 2
57060408 [1, 2]
57060408 [1, 2]
Passing mutable objects in function
def update(n):
print(id(n),n)
n.append(3)
print(id(n),n) main() 57060408
update()
def main():
n=[1,2]
print(id(n),n)
update(n)
n [ , , ] n
print(id(n),n)
main()
1 2 3
57060408 [1, 2]
57060408 [1, 2] The key point lies in the n.append(3)
57060408 [1, 2, 3]
method of list n. It is in-place update.
No new list objects created.
Passing mutable objects in function
def update(n):
print(id(n),n)
n.append(3)
print(id(n),n) main() 57060408
update()
def main():
n=[1,2]
print(id(n),n)
update(n)
n [ , , ] n
print(id(n),n)
main()
1 2 3 Clear concept: That’s why when
pass list object to update(),
updating the list in update() via
57060408 [1, 2] append() will also update the
57060408 [1, 2] original list in main().
57060408 [1, 2, 3]
57060408 [1, 2, 3]
Passing mutable objects in function
def update(n): def update(n): def update(n): def update(n):
print(id(n),n) print(id(n),n) print(id(n),n) print(id(n),n)
n.append(3) n.extend([3,4]) n+=[3,4] n=n+[3,4]
print(id(n),n) print(id(n),n) print(id(n),n) print(id(n),n)
def main():
team=["Kit","Dirk","Kevin","Jolly","Justin","Marco","Kiu"]
print("In main(): team before",id(team),team)
rename(team,"Kit","Kitty")
print("In main(): team after",id(team),team)
main()
Example 7
def rename(t,oldName,newName):
print("In rename(): t before",id(t),t)
for i,name in enumerate(t):
if(name==oldName):
t[i]=newName team references to
print("In rename(): t after",id(t),t) mutable list object
(list objects can be
def main():
team=["Kit","Dirk","Kevin","Jolly","Justin","Marco","Kiu"]
updated, in fact, the
print("In main(): team before",id(team),team) reference stored in each
rename(team,"Kit","Kitty") slot of the list can be
print("In main(): team after",id(team),team) updated to refer to other
Immutable str objects objects.)
main()
team [ , , , , , , ]
rename()
Example 7 oldName
Kit
main()
team [ , , , , , , ]
rename()
Example 7 oldName
Kit
main()
team [ , , , , , , ]
Tuple is immutable, it is different from list!
def update(n): def update(n): def update(n): def update(n):
print(id(n),n) print(id(n),n) print(id(n),n) print(id(n),n)
n.append(3) n[0]=3 n+=(3,4) n = n +(3,4)
print(id(n),n) print(id(n),n) print(id(n),n) print(id(n),n)
Passing mutable objects like (list, set, dict) to function, if the object is
in-place updated in function, the original object will also be updated.
In main(): salary before 52373904 10000
In raiseSalary(): sal before 52373904 10000
Checkpoint 1 In raiseSalary(): sal after 52374096 11000.0
In main(): salary after 52373904 10000
def raiseSalary(sal):
print("In raiseSalary(): sal before",id(sal),sal)
sal *= 1.1
print("In raiseSalary(): sal after",id(sal),sal)
def main():
salary=[10000,20000,30000]
print("In main(): salary before",id(salary[0]),salary[0])
raiseSalary(salary[0])
print("In main(): salary after",id(salary[0]),salary[0])
main()
def main():
salary=[10000,20000,30000]
print("In main(): salary[0] before",id(salary[0]),salary[0])
salary[0]=raiseSalary(salary[0])
print("In main(): salary[0] after",id(salary[0]),salary[0])
main()
Can you explain why the program can
update the salary of the first staff in main()
function?
In main(): salary[0] before 57485712 10000
In raiseSalary(): sal[0] before 57485712 10000
Checkpoint 3 TypeError: 'tuple' object does not support item
assignment
def raiseSalary(sal,eid):
print("In raiseSalary(): sal[0] before",id(sal[0]), sal[0])
sal[eid] *= 1.1
print("In raiseSalary(): sal[0] after",id(sal[0]), sal[0])
def main():
salary=(10000,20000,30000)
print("In main(): salary[0] before",id(salary[0]),salary[0])
raiseSalary(salary,0)
print("In main(): salary[0] after",id(salary[0]),salary[0])
main()
def main():
salary=[10000,20000,30000]
print("In main(): salary[0] before",id(salary[0]),salary[0])
raiseSalary(salary,0)
print("In main(): salary[0] after",id(salary[0]),salary[0])
main()
Can you explain why the program can
update the salary of the first staff in main()
function?
In main(): salary before 59551016 [10000, 20000, 30000]
In raiseSalary(): sal before 59551016 [10000, 20000, 30000]
Checkpoint 5 In raiseSalary(): sal after 59551016 [11000.0, 22000.0, 33000.0]
In main(): salary after 59551016 [11000.0, 22000.0, 33000.0]
def raiseSalary(sal,percentage=1.1):
print("In raiseSalary(): sal before",id(sal), sal)
for i,s in enumerate(sal):
sal[i] *= percentage
print("In raiseSalary(): sal after",id(sal), sal)
def main():
salary=[10000,20000,30000]
print("In main(): salary before",id(salary),salary)
raiseSalary(salary)
print("In main(): salary after",id(salary),salary)
main()
Can you explain why the program can
update the salary of all staff in main()
function?
In main(): salary before 64466136 [10000, 20000, 30000]
In raiseSalary(): sal before 64466136 [10000, 20000, 30000]
Checkpoint 6 In raiseSalary(): sal after 64466136 [10000, 20000, 30000]
In main(): salary after 64466136 [10000, 20000, 30000]
def raiseSalary(sal,percentage=1.1):
print("In raiseSalary(): sal before",id(sal), sal)
for s in sal:
s *= percentage
print("In raiseSalary(): sal after",id(sal), sal)
def main():
salary=[10000,20000,30000]
print("In main(): salary before",id(salary),salary)
raiseSalary(salary)
print("In main(): salary after",id(salary),salary)
main()
Can you explain why the program cannot
update the salary of all staff in main()
function?
Chapter 7B.
End
ENGG 1330 Computer Programming I
Dr. Chui Chun Kit and Dr. Dirk Schnieders
Slides prepared by - Dr. Chui Chun Kit (http://www.cs.hku.hk/~ckchui/) and Dr. Dirk Schnieders for students in ENGG1330. For other uses, please email : [email protected]