EX 41: One piece of code I'm not understanding

So I’ve been meticulously going through 41 and after entering in all the code for oop_test.py and making sure it worked, I went back and looked at the code line by line so that I could understand what it was doing but also understand how it was flowcharting. I did that by adding print() statements at various points to see what the variables/lists were doing.

I figured most of it out but there’s one section that still vexes me. It’s here…

    for sentence in snippet, phrase:
        print("sentence: ", sentence)
        # this is how you duplicate a list or string
        result = sentence [:]
        print("result: ", result)

The print statements are my additions and they’re also the reason for this post because what I see in Powershell for this section is this:

sentence:  class %%%(%%%):
result:  class %%%(%%%):

There appears to be no difference between the sentence or result variable. Which raises the question of why this line is even needed:

result = sentence [:]

Since there’s apparently no difference between variables after this executes, I’m wondering why you couldn’t just eliminate that line of code entirerly and just use “sentence” wherever you saw “result” in the code. What am I missing here?

I’m also not clear on what [:] after sentence is supposed to do. I tried to research it but didn’t find anything that seemed applicable.

BTW, my mind is still a bit blown by how this works…

    for sentence in snippet, phrase:

I wouldn’t have figured it out if I hadn’t inserted those print statements.

It’s in the comment in your code. The empty slice operator creates an exact copy of a sequence such that when you change the copy, the original will not be affected.

Here’s me playing around with that in the REPL:

>>> l1 = [1,2,3]
>>> l2 = l1
>>> l2.append(4)
>>> l1
[1, 2, 3, 4]
>>> l2
[1, 2, 3, 4]
>>> l3 = l1[:]
>>> l3.append(5)
>>> l1
[1, 2, 3, 4]
>>> l3
[1, 2, 3, 4, 5]
1 Like

Ok…that makes sense as far as what [:] does and why it might be needed.

However it’s still not clear to me why it might be needed in this exercise. Here sentence is something that changes with every iteration of the for loop and it changes after result was appended to results so there appears to be no opportunity in the code for cross contamination of sentence if something changes in result. Consider this modification where I removed [:] (and also added more print statements to track the execution)…

    for sentence in snippet, phrase:
        print("sentence (before result defined): ", sentence)
        # this is how you duplicate a list or string
        result = sentence
        print("result: ", result)
        print("sentence (after result defined): ", sentence)

        # replaces any instance of %%% in the snippet and corresponding
        # phrase with a class_name if class_names has anything in its list
        for word in class_names:
            result = result.replace("%%%", word, 1)
            print("class_names result: ", result)
            print("class_names sentence: ", sentence)

        # replaces any instance of *** in the snippet and corresponding
        # phrase with an other_name if other_names has anything in its list
        for word in other_names:
            result = result.replace("***", word, 1)
            print("other_names result: ", result)
            print("other_names sentence: ", sentence)

        # replaces any instance of @@@ in the snippet and corresponding
        # phrase with a param_name if param_names has anything in its list
        for word in param_names:
            result = result.replace("@@@", word, 1)
            print("param_names result: ", result)
            print("param_names sentence: ", sentence)

        results.append(result)
        print("results: ", results)
        print("result (post results.append(result)): ", result)
        print("sentence (post results.append(result)): ", sentence)

results in this in Powershell:

PS C:\Users\dswal\AppData\Local\Programs\Python\Python36\Doug> python oop_test.py english
sentence (before result defined):  ***.***(@@@)
result:  ***.***(@@@)
sentence after result defined:  ***.***(@@@)
other_names result:  boot.***(@@@)
other_names sentence:  ***.***(@@@)
other_names result:  boot.believe(@@@)
other_names sentence:  ***.***(@@@)
param_names result:  boot.believe(beam, duck)
param_names sentence:  ***.***(@@@)
results:  ['boot.believe(beam, duck)']
result (post results.append(result)):  boot.believe(beam, duck)
sentence (post results.append(result)):  ***.***(@@@)
sentence (before result defined):  From *** get the *** function, call it with params self, @@@.
result:  From *** get the *** function, call it with params self, @@@.
sentence after result defined:  From *** get the *** function, call it with params self, @@@.
other_names result:  From boot get the *** function, call it with params self, @@@.
other_names sentence:  From *** get the *** function, call it with params self, @@@.
other_names result:  From boot get the believe function, call it with params self, @@@.
other_names sentence:  From *** get the *** function, call it with params self, @@@.
param_names result:  From boot get the believe function, call it with params self, beam, duck.
param_names sentence:  From *** get the *** function, call it with params self, @@@.
results:  ['boot.believe(beam, duck)', 'From boot get the believe function, call it with params self, beam, duck.']
result (post results.append(result)):  From boot get the believe function, call it with params self, beam, duck.
sentence (post results.append(result)):  From *** get the *** function, call it with params self, @@@.
From boot get the believe function, call it with params self, beam, duck.

As you can see sentence never changes its value even though result does. And that’s with [:] removed from ressult = sentence[:].

So with [:] included or not, the results don’t seem to change. So why use it here?

Also consider this modification where I removed result from the code and just used sentence in its place:

    for sentence in snippet, phrase:

        # replaces any instance of %%% in the snippet and corresponding
        # phrase with a class_name if class_names has anything in its list
        for word in class_names:
            sentence = sentence.replace("%%%", word, 1)

        # replaces any instance of *** in the snippet and corresponding
        # phrase with an other_name if other_names has anything in its list
        for word in other_names:
            sentence = sentence.replace("***", word, 1)

        # replaces any instance of @@@ in the snippet and corresponding
        # phrase with a param_name if param_names has anything in its list
        for word in param_names:
            sentence = sentence.replace("@@@", word, 1)

        results.append(sentence)

This change also appears to work just fine with the code. So I’m back where I started at the beginning of this thread wondering why result = sentence[:] is even in the code because it seems to be superfluous to the code functioning correctly and we could use the code with sentence as the only variable needed. What am I missing here?

I also don’t see why it’s needed here. Maybe you’re not missing anything.

1 Like
A free service run by Zed A. Shaw for learncodethehardway.org.