Learn Python the Hard way, exercise 25, not getting expected result

I'm doing exercise 25 of Learn Python the Hard Way and I'm not getting the expected result. When I call print_first_word on the parameter words (which is an list), I type into the shell:

ex25.print_first_word(words)

I am told I should see:

All

Instead, I see

wait.

It's worth mentioning that words was:

['All', 'good', 'things', 'come', 'to', 'those', 'who', 'wait.']

Here is my code:

def break_words(stuff):
    """This Function will break up words for us."""
    words = stuff.split(' ')
    return words

def sort_words(words):
    """Sorts the words."""
    return sorted(words)

def print_first_word(words):
    """Prints the first word after popping it off."""
    word = words.pop(0)
    print word

def print_last_word(words):
    """Prints the last word after popping it off."""
    word = words.pop(-1)
    print word

def sort_sentence(sentence):
    """Takes in a full sentence and returns the sorted words."""
    words = break_words(sentence)
    return sort_words(words)

def print_first_and_last(sentence):
    """Prints the first and last words of the sentence"""
    words = break_words(sentence)
    print_first_word(words)
    print_last_word(words)

def print_first_and_last_sorted(sentence):
    """Sorts the words then prints the first and last one."""
    words = sort_sentence(sentence)
    print_first_word(words)
    print_last_word(words)

Upvotes: 0

Views: 1422

Answers (4)

The problem was that I was not importing the file I thought I was. Someone who commented on my question at Learn Python The Hard Way, Exercise 25, module has no attribute 'print_last_word' suggested I

print ex25.__file__

This showed me the file I was actually importing from. Then, I made sure to import from the correct path.

Please let me know if this is better posted as an update/edit to my question. Thanks!

Upvotes: 0

Ashish
Ashish

Reputation: 14707

As I said I did not change is single character in your code and it is running perfectly fine. Here is what I have

    def print_first_word(words):
    """Prints the first word after popping it off."""
    word = words.pop(0)
    print word

    words=['All', 'good', 'things', 'come', 'to', 'those', 'who', 'wait.']

    print_first_word(words)

And the result is All

Upvotes: 1

Matthew
Matthew

Reputation: 306

There are two things you should keep in mind. First, the pop() method modifies the list it's used on; once you access an item using pop(), it's no longer in the list. Look at this sequence of commands:

>>> words = ['All', 'good', 'things', 'come', 'to', 'those', 'who', 'wait.']
>>> words.pop(0)
'All'
>>> words.pop(0)
'good'
>>> words.pop(0)
'things'
>>> words.pop(0)
'come'
>>> words.pop(0)
'to'
>>> words.pop(0)
'those'
>>> words.pop(0)
'who'
>>> words.pop(0)
'wait.'

>>> words.pop(0)

Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    words.pop(0)
IndexError: pop from empty list
>>> 

Second, and this is pretty confusing, lists are passed by reference. What this means is is that when you call print_first_word(words), words.pop(0) doesn't just modify a local variable within your function. It modifies your original list! So, if you call print_first_word(words) multiple times, its output will differ each time, similar to what you see above.

You can fix this by using word = words[0], which merely retrieves the value at 0, instead of word = words.pop(0).

Upvotes: 1

Adam Smith
Adam Smith

Reputation: 54223

My guess is that you're doing this in IDLE (or another interactive shell) and your previous "test runs" have affected your input. Try printing words first, and see if it is what you expect it to be. Your code looks right.

Remember that list.pop (as you have in your function print_first_word(words) actually REMOVES its target from the list. That is to say:

words = ['All', 'good', 'things', 'come', 'to', 'those', 'who', 'wait.']
words.pop(0) # returns 'All', but since I don't assign it anywhere, who cares
print(words)
# ['good', 'things', 'come', 'to', 'those', 'who', 'wait.']

If you're NOT TRYING to remove an element from a list, don't pop it, just slice it.

words = ['All', 'good', 'things', 'come', 'to', 'those', 'who', 'wait.']
words[0] # ALSO returns 'All', though again I'm not doing anything with it
print(words)
# ['All', 'good', 'things', 'come', 'to', 'those', 'who', 'wait.']

Upvotes: 1

Related Questions