Python Forum

Full Version: For loops, strings and printing words with even characters
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I’ve got a string: "Secret agents are super good at staying hidden."

I’m trying to use a for loop to print out only the words with an even number of characters.

In my code below, I’ve assigned the string to a variable. I’ve split each word up into items in a new list by using the split function. Then I’ve counted the length of each item and assigned it to a new variable called, counted_string. Then I iterate through each item. I take each item and apply a modulus of two. If the remainder is 0 (meaning the word has an even number of characters) only then that particular item is printed. This is what I am trying to do in following code snippet I’ve written:

mystring = "Secret agents are super good at staying hidden."
mystring.split()
counted_string = len(mystring)
int(counted_string)
for i in counted_string:    
    if i %2 == 0:
        print(i)
I was expecting this output:
Quote:Secret
agents
good
at

Instead I get this traceback:
TypeError                                 Traceback (most recent call last)
<ipython-input-28-5b7261c4eed7> in <module>()
      3 counted_string = len(mystring)
      4 int(counted_string)
----> 5 for i in counted_string:
      6     if i %2 == 0:
      7         print(i)

TypeError: 'int' object is not iterable
I'm doing something wrong at line 5. The traceback is saying that my counted_string variable is not iterable (because it’s an integer?). Only strings and lists are iterable. So if I substitute counted_string in my for loop with the original mystring variable, I don’t get any output.

Can someone better explain why my code is actually doing and how I can get the desired/expected output?

For my future reference, this forum thread refers to Task #2 in Jose Portilla’s so called 04-Field-Readiness-Exam-2 in his “Narrative Journey” Udemy Python course material (on GitHub: Pierian-Data/Python-Narrative-Journey).
(Sep-13-2018, 02:05 PM)Drone4four Wrote: [ -> ]
mystring = "Secret agents are super good at staying hidden."
mystring.split()

Strings are immutable objects - meaning that they cannot be changed "in-place". You essentially create a temporary list object without assigning the result - so that list is lost

(Sep-13-2018, 02:05 PM)Drone4four Wrote: [ -> ]
counted_string = len(mystring)
int(counted_string)
Result of len function is integer - and the second line again does nothing

(Sep-13-2018, 02:05 PM)Drone4four Wrote: [ -> ]
for i in counted_string:    
    if i %2 == 0:
        print(i)

In Python, you iterate over lists directly; if you need index - you use enumerate function; if you want to iterate over range of values - you use range function (just to explain your mistake, don't need it here)

This video is highly recommended for those learning how to loop in Python
Thanks for the your help so far, volcano63.

(Sep-13-2018, 02:26 PM)volcano63 Wrote: [ -> ]Strings are immutable objects - meaning that they cannot be changed "in-place". You essentially create a temporary list object without assigning the result - so that list is lost
By immutable, do you mean that strings in general cannot be altered or changed? Certainly it's possible to modify a string, just the way I originally tried to do so is faulty. I've re-assigned the split of mystring back to the mystring variable. See line 2 of my script copied below.

Quote:Result of len function is integer - and the second line again does nothing
I've commented out this line.

Here is what my script looks like now:
mystring = "Secret agents are super good at staying hidden."
mystring = mystring.split()
counted_string = len(mystring)
# int(counted_string)
for word in mystring:    
    if counted_string %2 == 0:
        print(word)
It runs without a traceback but it still does do what I've set out to do. Here is the output:
Secret
agents
are
super
good
at
staying
hidden.
I am trying to only print the words which have an even number of characters. I've got more material to go over, as you've suggested:
Quote:In Python, you iterate over lists directly; if you need index - you use enumerate function; if you want to iterate over range of values - you use range function (just to explain your mistake, don't need it here)

This video is highly recommended for those learning how to loop in Python

I'll review both my Udemy instructor's videos on enumeration and watch this YouTube video by Ned Batchelder that you've shared.
(Sep-13-2018, 03:07 PM)Drone4four Wrote: [ -> ]By immutable, do you mean that strings in general cannot be altered or changed? Certainly it's possible to modify a string,
yes, immutable means you cannot change string. what you do is to reassign variable name. i.e. your variable name points to different object, not that you changed the string. Just for comparison - lists are mutable. so you can do:
>>> some_list = [1, 2, 3]
>>> id(some_list)
139888340672392
>>> some_list[0] = 4
>>> some_list
[4, 2, 3]
>>> id(some_list)
139888340672392
as you can see you can change the list, but it is the same object (same id)
you cannot change a string.
(Sep-13-2018, 03:07 PM)Drone4four Wrote: [ -> ]
mystring = "Secret agents are super good at staying hidden."
mystring = mystring.split()
counted_string = len(mystring)
# int(counted_string)
for word in mystring:    
    if counted_string %2 == 0:
        print(word)
counted_string is the length of the list (8), you need it to be the length of EACH string (word) as you go through the loop.
At precisely 13 minutes and 17 seconds into Ned Batchelder’s talk on YouTube on loops and iterables in Python, I’ve struck gold!

Based on that slide, I modified my script so it reads:
mystring = "Secret agents are super good at staying hidden.".split()
for word in mystring:    
    if len(word) % 2 == 0:
        print(word)
My expected output now matches my actual output.

Thanks again volcano63 for Ned Batchelder's enormously helpful YouTube video!
Now to blow your mind with a list comprehension (for the sake of learning and being Pythonic):

mystring = [word for word in "Secret agents are super good at staying hidden.".split() if len(word) % 2 == 0]
print(", ".join(mystring))
(Oct-05-2018, 02:07 AM)stullis Wrote: [ -> ]Now to blow your mind with a list comprehension (for the sake of learning and being Pythonic):

mystring = [word for word in "Secret agents are super good at staying hidden.".split() if len(word) % 2 == 0]
print(", ".join(mystring))
Just for a laugh,
print(*[word for word in "Secret agents are super good at staying hidden.".split() if not len(word) % 2], sep=", ")
(Oct-05-2018, 01:03 AM)Drone4four Wrote: [ -> ]Thanks again volcano63 for Ned Batchelder's enormously helpful YouTube video!

You are welcome. Maybe one day I will watch it myself (closing barn doors and bolted horses come to mind Smile )