Aliasing and While Loops

Today, we will discuss the following:

  • Mutability and aliasing in Python

  • While loops

Value vs Identity and Aliasing

  • An objects identity never changes in Python once it has been created. You can think of it as the object’s address in memory.

  • On the other hand, the value of some objects can change.

  • Objects whose values can change are called mutable; objects whose values cannot change are called immutable

  • The is operator compares the identity of two objects, and the == operator compares the value (contents) of an object

  • The id() function returns an integer representing its identity

Any assignment or operation that creates a new name for an existing object implicitly creates an alias (a new name). Immutable and mutable objects behave differently with respect to aliasing.

Let’s see some examples using strings (immutable) and lists (mutable).

# strings are immutable
word = "Williams"
# college is an alias (second name) for word 
college = word
word == college
True
print(id(word), id(college))
4423941680 4423941680
# they are the same object
word is college
True
# changing the value, also changes the identity
word = "Wellesley"
print(id(word), id(college))
4424633328 4423941680
# word and college are no longer the same
word is college
False
word = word.upper()
word
'WELLESLEY'
id(word)
4424329008
list1 = [1, 2, 3]

# list2 is an alias for list1
list2 = list1
list1 is list2
True
id(list1)
4424631424
id(list2)
4424631424
list1.append(4)
# list2 has also changed!  
# this is different than our string example above
list2
[1, 2, 3, 4]
id(list2)
4424631424
# still the same
id(list1)
4424631424
list1 = [1, 2, 3]
list2 = list1
list3 = [1, 2, 3]
# same values?
list1 == list2 == list3
True
# same identities?
list3 is list1
False

Understanding Aliasing

Let us try out some tricky examples that illustrate how aliasing manifests itself in lists in Python.

nums = [23, 19]
words = ['hello', 'world']
mixed = [12, nums, 'nice', words]
words.append('sky')
mixed
[12, [23, 19], 'nice', ['hello', 'world', 'sky']]
id(mixed)
4424637440
id(nums)
4424327232
id(mixed[1])
4424327232
mixed[1].append(27)
nums
[23, 19, 27]
mixed
[12, [23, 19, 27], 'nice', ['hello', 'world', 'sky']]
nums
[23, 19, 27]
mixed
[12, [23, 19, 27], 'nice', ['hello', 'world', 'sky']]

While loops: A New Iteration Mechanism

  • for loops iterate over a pre-determined sequence and stop at the end of the sequence

  • On the other hand, while loops are useful when we don’t know in advance when to stop

  • A while loop will keep iterating while the boolean condition in the parentheses is True and will halt if the condition fails to hold (is False)

def printHalves(n):
    while n > 0: 
        print(n)
        n = n//2
printHalves(100)
100
50
25
12
6
3
1

Infinite loops

An infinite loop occurs when a loop’s exit condition never turns false. Generally, we want to avoid this. Occasionally, there are reasons to intentionally create infinite loops. In the example below, the infinite loop exits when the return statement in the loop is reached.

def computeSum():
    sum = 0
    while True:
        prompt = 'Please enter a positive number: '
        num = int(input(prompt))
        if num < 0:
            return sum
        sum += num
computeSum()
---------------------------------------------------------------------------
StdinNotImplementedError                  Traceback (most recent call last)
/var/folders/md/kwd9nc_d2ns0hw9wsvdrnt2c0000gn/T/ipykernel_98444/2199867258.py in <module>
----> 1 computeSum()

/var/folders/md/kwd9nc_d2ns0hw9wsvdrnt2c0000gn/T/ipykernel_98444/2553120940.py in computeSum()
      3     while True:
      4         prompt = 'Please enter a positive number: '
----> 5         num = int(input(prompt))
      6         if num < 0:
      7             return sum

/usr/local/lib/python3.9/site-packages/ipykernel/kernelbase.py in raw_input(self, prompt)
   1001         """
   1002         if not self._allow_stdin:
-> 1003             raise StdinNotImplementedError(
   1004                 "raw_input was called, but this frontend does not support input requests."
   1005             )

StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
def computeSum():
    sum = 0
    num = 0
    while num >= 0:
        prompt = 'Please enter a positive number: '
        num = int(input(prompt))
        sum += num
    return sum
computeSum()
---------------------------------------------------------------------------
StdinNotImplementedError                  Traceback (most recent call last)
/var/folders/md/kwd9nc_d2ns0hw9wsvdrnt2c0000gn/T/ipykernel_98444/2199867258.py in <module>
----> 1 computeSum()

/var/folders/md/kwd9nc_d2ns0hw9wsvdrnt2c0000gn/T/ipykernel_98444/4058298043.py in computeSum()
      4     while num >= 0:
      5         prompt = 'Please enter a positive number: '
----> 6         num = int(input(prompt))
      7         sum += num
      8     return sum

/usr/local/lib/python3.9/site-packages/ipykernel/kernelbase.py in raw_input(self, prompt)
   1001         """
   1002         if not self._allow_stdin:
-> 1003             raise StdinNotImplementedError(
   1004                 "raw_input was called, but this frontend does not support input requests."
   1005             )

StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.