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))
4430164464 4430164464
# they are the same object
word is college
True
# changing the value, also changes the identity
word = "Amherst"
print(id(word), id(college))
4430214960 4430164464
# word and college are no longer the same
word is college
False
word = word.upper()
word
'AMHERST'
id(word)
4430216560
list1 = [1, 2, 3]

# list2 is an alias for list1
list2 = list1
list1 is list2
True
id(list1)
4430407104
id(list2)
4430407104
list1.append(4)
# list2 has also changed!  
# this is different than our string example above
list2
[1, 2, 3, 4]
id(list2)
4430407104
# still the same
id(list1)
4430407104
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)
4430344448
id(nums)
4430361152
id(mixed[1])
4430361152
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)
Input In [37], in <cell line: 1>()
----> 1 computeSum()

Input In [36], in computeSum()
      3 while True:
      4     prompt = 'Please enter a positive number: '
----> 5     num = int(input(prompt))
      6     if num < 0:
      7         return sum

File ~/cs-courses/cs134-f22/staff/_env/lib/python3.9/site-packages/ipykernel/kernelbase.py:1174, in Kernel.raw_input(self, prompt)
   1167 """Forward raw_input to frontends
   1168 
   1169 Raises
   1170 ------
   1171 StdinNotImplementedError if active frontend doesn't support stdin.
   1172 """
   1173 if not self._allow_stdin:
-> 1174     raise StdinNotImplementedError(
   1175         "raw_input was called, but this frontend does not support input requests."
   1176     )
   1177 return self._input_request(
   1178     str(prompt),
   1179     self._parent_ident["shell"],
   1180     self.get_parent("shell"),
   1181     password=False,
   1182 )

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)
Input In [39], in <cell line: 1>()
----> 1 computeSum()

Input In [38], in computeSum()
      4 while num >= 0:
      5     prompt = 'Please enter a positive number: '
----> 6     num = int(input(prompt))
      7     sum += num
      8 return sum

File ~/cs-courses/cs134-f22/staff/_env/lib/python3.9/site-packages/ipykernel/kernelbase.py:1174, in Kernel.raw_input(self, prompt)
   1167 """Forward raw_input to frontends
   1168 
   1169 Raises
   1170 ------
   1171 StdinNotImplementedError if active frontend doesn't support stdin.
   1172 """
   1173 if not self._allow_stdin:
-> 1174     raise StdinNotImplementedError(
   1175         "raw_input was called, but this frontend does not support input requests."
   1176     )
   1177 return self._input_request(
   1178     str(prompt),
   1179     self._parent_ident["shell"],
   1180     self.get_parent("shell"),
   1181     password=False,
   1182 )

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