[Tutor] Problem with code interating thri a list

Danny Yoo dyoo at hashcollision.org
Tue Aug 2 19:52:22 EDT 2016


On Tue, Aug 2, 2016 at 7:59 AM, Chris Clifton via Tutor
<tutor at python.org> wrote:

> My Logic:  Since a string is immutable, I converted it to a list to separate out the characters and keep them in order.  Idea is to change the case of the characters in the list then run a join to convert it back to a string.


Hi Chris,

Yes, that's reasonable.  One way you can imagine doing this is
"accumulating" a result, rather than doing in-place edits.


For example, let's say that I have a list of numbers, and would like a
function to return their squares.  Toy example: it's meant as a finger
exercise.  Try writing it first.

...

Ok, here's one approach.  We *could* do it like this:

##############################
def squares(nums):
    copied = nums[:]
    for index in range(len(copied)):
        copied[index] = copied[index]**2
    return copied
##############################

where we copy the list, and then do in-place edits of each element.


Note Alan's warning!  If we had tried to do:

####################################
def squares(nums):
    copied = nums[:]
    for index in range(len(copied)):
        item = copied[index]
        item = item**2                  ## buggy!
    return copied
####################################

this would not have the effect we want.


Why not?

If it helps to see what's going on, try the Online Python Tutor visualizer.

Compare the "buggy" version:

http://www.pythontutor.com/visualize.html#code=def%20squares(nums%29%3A%0A%20%20%20%20copied%20%3D%20nums%5B%3A%5D%0A%20%20%20%20for%20index%20in%20range(len(copied%29%29%3A%0A%20%20%20%20%20%20%20%20item%20%3D%20copied%5Bindex%5D%0A%20%20%20%20%20%20%20%20item%20%3D%20item**2%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%23%20buggy!%0A%20%20%20%20return%20copied%0A%20%20%20%20%0Asquares(%5B1,%202,%203%5D%29&cumulative=false&curInstr=0&heapPrimitives=false&mode=display&origin=opt-frontend.js&py=2&rawInputLstJSON=%5B%5D&textReferences=false

versus the one that works:


http://www.pythontutor.com/visualize.html#code=def%20squares(nums%29%3A%0A%20%20%20%20copied%20%3D%20nums%5B%3A%5D%0A%20%20%20%20for%20index%20in%20range(len(copied%29%29%3A%0A%20%20%20%20%20%20%20%20copied%5Bindex%5D%20%3D%20copied%5Bindex%5D**2%0A%20%20%20%20return%20copied%0A%20%20%20%20%0Asquares(%5B1,%202,%203%5D%29&cumulative=false&curInstr=0&heapPrimitives=false&mode=display&origin=opt-frontend.js&py=2&rawInputLstJSON=%5B%5D&textReferences=false


Do you see and understand the difference?  Please feel free to ask questions.


***

Another way that gets a similar result is to create a fresh new list
and append, ignoring indices altogether:

##############################
def squares(nums):
    result = []
    for n in nums:
        result.append(n**2)
    return result
##############################

This is more preferred because we don't normally have to deal with
indices.  It works because we can depend on the order in which we're
walking over the list elements, and we're appending to the end of the
list, so the list of the transformed results will match in lockstep
with the order of the input.


More information about the Tutor mailing list