Python language basics 28: modifying the referenced value

Introduction

In the previous post we discussed the basics of value and reference equality. We saw how to evaluate these equality types with the ‘==’ and ‘is’ operators. We also found an important difference between how value and reference types are handled in memory.

In this post we’ll look at another feature related to objects and equality, namely the effects of changing the referenced value.

Modifications through assignment

We’ve seen the assignment operator ‘=’ in action before:

x = 5

We can read this as ‘x becomes equal to 5’ or ‘x is assigned the value of 5’. This helps us distinguish in words between the ‘=’ and ‘==’ operators where ‘==’ tests for value equality as we saw in the previous post.

Let’s see what happens in the following bit of code:

x = 5
y = x
x = 3
print(x)
print(y)

Without knowing the printed values we could argue as follows about the expected outcome:

  • The object called ‘x’ points to a value 5
  • The object called ‘y’ will point to the same value as ‘x’ i.e. points to the previously created value 5
  • We change the value of ‘x’ to 3
  • As y and x point to the same value even y will be equal to 3
  • Therefore both print statements will print 3

That’s in fact only partially true. The first two statements are true: x and y will point to the same value 5. However, x = 3 will NOT change the previously stored value 5 directly. Instead, a new integer value 3 will be created on the heap and x will instead point to that value. Its pointer has been redirected from 5 to 3. The object y still points to 5. The statement x = 3 does NOT change the stored value 5 directly. Therefore the print statements will print 3 and 5.

This feature is called object immutability in programming. The English word ‘immutable’ means something that cannot mutate, i.e. cannot change, cannot be changed. At first sight the above code seems to alter the value of x from 5 to 3 but that’s only appearance.

We see the same behaviour for strings:

s1 = 'hello'
s2 = s1
s1 = 'bye'
print(s1)
print(s2)

This prints…

bye
hello

The ‘=’ assignment operator therefore only assigns a new value to an object. We can see that in the following example as well with a list:

myFirstList = ["small", "medium", "large", "x-large"]
mySecondList = myFirstList
myFirstList = ["smallish", "medium", "large", "x-large", "xx-large"]
print(myFirstList)
print(mySecondList)

myFirstList is assigned a completely new value in the third line. The assignment operator doesn’t modify the originally assigned list of strings at all. Therefore the print statements give the following:

[‘smallish’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’]
[‘small’, ‘medium’, ‘large’, ‘x-large’]

Modifications through direct access

In contrast to the above if you directly access parts of the object in memory it will affect any other variable that references that object. Consider the following dictionary-based example:

myFirstDictionary = {"S": "Small", "M": "Medium", "L": "Large", "XL": "X-Large"}
mySecondDictionary = myFirstDictionary
myFirstDictionary["S"] = "Smallish"
myFirstDictionary["XXL"] = "XX-Large"
print(myFirstDictionary)
print(mySecondDictionary)

What do you think these print statements will give you? mySecondDictionary and myFirstDictionary point to the same dictionary object in memory. We directly access that dictionary object using the [] operator for dictionaries. mySecondDictionary will indeed also be affected by the direct change applied to myFirstDictionary:

{‘XXL’: ‘XX-Large’, ‘S’: ‘Smallish’, ‘L’: ‘Large’, ‘XL’: ‘X-Large’, ‘M’: ‘Medium’}
{‘XXL’: ‘XX-Large’, ‘S’: ‘Smallish’, ‘L’: ‘Large’, ‘XL’: ‘X-Large’, ‘M’: ‘Medium’}

Here’s a similar example using lists:

myFirstList = ["small", "medium", "large", "x-large"]
mySecondList = myFirstList
myFirstList[0] = "smallish"
print(myFirstList)
print(mySecondList)

…which gives…

[‘smallish’, ‘medium’, ‘large’, ‘x-large’]
[‘smallish’, ‘medium’, ‘large’, ‘x-large’]

It is very important for the programmer to keep in mind that if an object is mutable, i.e. can be modified directly like in the case of a dictionary or a list then any other variable referencing the same object will also be affected. Do not assume that the assignment operator ‘=’ somehow creates a copy as in mySecondList = myFirstList. mySecondList won’t magically be an independent copy of myFirstList that you can modify separately. myFirstList and mySecondList will point to the same object in memory with all its consequences. We’ll look at one of those consequences in the next post.

Read all Python-related posts on this blog here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Python language basics 28: modifying the referenced value

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: