464,384 Members | 1,081 Online
Need help? Post your question and get tips & solutions from a community of 464,384 IT Pros & Developers. It's quick & easy.

# newbie question: for loop within for loop confusion

 P: n/a Hi, I'm studying python via the exellent book "How to think like a python programmer" by Allen Downey. Noob question follows... animals.txt is a list of animals, each on a separate line: "aardvard, bat, cat, dog, elephant, fish, giraffe, horse, insect, jackelope" I want to loop through the list of words and print words that don't have any "avoid" letter in them. def hasnolet(avoid): fin = open('animals.txt') for line in fin: word = line.strip() for letter in avoid: if letter in word: break else: print word hasnolet('abcd') Why doesn't the function above work? It returns: dog dog dog fish fish fish fish horse horse horse horse inchworm inchworm thanks for any help. takayuki Jun 27 '08 #1
17 Replies

 P: n/a In article , takayuki

 P: n/a On 09:23, lunedÃ¬ 16 giugno 2008 takayuki wrote: word = line.strip() Try word= line.split() and at the end of the loop add one more print to go to new line. -- Mailsweeper Home : http://it.geocities.com/call_me_not_now/index.html Jun 27 '08 #3

 P: n/a takayuki wrote: for letter in avoid: if letter in word: break else: print word Take the word 'dog', for example. What the above loop is doing is basically this: 1. for letter in avoid uses 'a' first 2. is 'a' in 'dog'? 3. no, so it prints 'dog' 4. go back to for loop, use 'b' 5. is 'b' in 'dog'? 6. no, so it prints 'dog' again 7. go back to for loop..... Since it goes sequentially through 'abcd', it will say that the first three letters are not in 'dog', and therefore print it three times. Then it finally sees that 'd' *is* in dog, so it skips it the fourth time through the loop. Jun 27 '08 #4

 P: n/a takayuki wrote: inchworm inchworm P.S. Why does 'inchworm' only print twice? Or is that not the full output? Jun 27 '08 #5

 P: n/a Thanks to everyone for the excellent advice. Roy: I did as you suggested and could see after staring at the output for awhile what was going on. The print statements really helped to put a little light on things. Yes, I agree that "learning to fish" is the best way. John: There were two "inchworms" because "c" is in "inchworm" so it shouldn't print. Thanks for your detailed description of the for loop. The Saint: i'll check out the word = line.split() command. After much flailing about, here's a loop that is working: def hasnolet2(avoid): fin = open('animals.txt') for line in fin: word = line.strip() length = len(avoid) x = 0 noprint = 0 while length -1 >= x: if avoid[x] in word: noprint = noprint + 1 x = x + 1 if noprint == 0: print word hasnolet2('abcd') which should return: fish horse hasnolet2('abcd') Jun 27 '08 #6

 P: n/a On Jun 16, 2:35*pm, takayuki = x: * * * * * * * * if avoid[x] in word: * * * * * * * * * * * * noprint = noprint + 1 * * * * * * * * x = x + 1 * * * * if noprint == 0: * * * * * * * * print word There seems to be an indendation problem (presumably the code from length = len(avoid) onwards should be inside the loop). But apart from that, we can try to make this more 'pythonic'. First, python has a 'for' statement that's usually better than using while. We use the 'range' function that produces the numbers 0, 1, ... length - 1, and x takes the value of these in turn. Here's the last bit of your code rewritten like this: noprint = 0 for x in range(length): if avoid[x] in word: noprint += 1 if noprint == 0: print word But better, rather than using 'x' as an index, we can loop over letters in avoid directly. I've changed 'noprint' to be a boolean 'should_print' too here. should_print = True for letter in avoid: if letter in word: should_print = False if should_print: print word We can eliminate 'should_print' completely, by using 'break' and 'else'. A break statement in a loop causes the loop to end. If the loop doesn't break, the 'else' code is run when the loop's over. for letter in avoid: if letter in word: break else: print word This is almost the same as your original code, but the 'else' is attached to the 'for' rather that the 'if'! Finally, in Python 2.5 you can write this: if not any(letter in word for letter in avoid): print word I think this is the best solution, as it's readable and short. -- Paul Hankin Jun 27 '08 #7

 P: n/a "takayuki"

 P: n/a "takayuki"

 P: n/a On Jun 16, 7:17 am, Paul Hankin = x: if avoid[x] in word: noprint = noprint + 1 x = x + 1 if noprint == 0: print word There seems to be an indendation problem (presumably the code from length = len(avoid) onwards should be inside the loop). But apart from that, we can try to make this more 'pythonic'. First, python has a 'for' statement that's usually better than using while. We use the 'range' function that produces the numbers 0, 1, ... length - 1, and x takes the value of these in turn. Here's the last bit of your code rewritten like this: noprint = 0 for x in range(length): if avoid[x] in word: noprint += 1 if noprint == 0: print word But better, rather than using 'x' as an index, we can loop over letters in avoid directly. I've changed 'noprint' to be a boolean 'should_print' too here. should_print = True for letter in avoid: if letter in word: should_print = False if should_print: print word We can eliminate 'should_print' completely, by using 'break' and 'else'. A break statement in a loop causes the loop to end. If the loop doesn't break, the 'else' code is run when the loop's over. for letter in avoid: if letter in word: break else: print word This is almost the same as your original code, but the 'else' is attached to the 'for' rather that the 'if'! Finally, in Python 2.5 you can write this: if not any(letter in word for letter in avoid): print word I think this is the best solution, as it's readable and short. Alternatively, you could use sets: if not(set(word) & set(avoid)): print word (parentheses added for clarity.) Jun 27 '08 #10

 P: n/a On Jun 15, 6:23 pm, takayuki

 P: n/a On Jun 16, 2:34 pm, Thomas Hill

 P: n/a Paul, Thank you for the informative reply. Yes, I created the indent problem when manually copying the original script when I posted. (I'm using an old laptop to study python and posting here using the desktop.) Your examples really helped. Last night I played with using a for loop instead of a while loop and got it working, but your examples really clarified things. This loop was particularly interesting because I didn't know the else could be attached to the for. Attaching it to the for solved a lot of problems. for letter in avoid: if letter in word: break else: print word I've printed out this whole thread and will be playing with your and others' solutions. I love this one for its conciseness, but will have to play with it to get my head around it. if not any(letter in word for letter in avoid): print word Thanks again. takayuki Jun 27 '08 #13

 P: n/a On Jun 17, 6:34 am, Thomas Hill

 P: n/a takayuki wrote: I'm early on in my python adventure so I'm not there yet on the strip command nuances. I'm reading "How to think like a python programmer" first. It's great. Then "Learning python". I've read parts of Dive into Python and will work through it fully when I'm a little farther along. Yeah, I really recommend Learning Python for getting the basics first. It's very thorough in that regard. Dive Into Python is *not* for beginners. I'm sorry if people disagree, but it's just not. Jun 27 '08 #15

 P: n/a takayuki wrote: Paul, Thank you for the informative reply. Yes, I created the indent problem when manually copying the original script when I posted. (I'm using an old laptop to study python and posting here using the desktop.) Your examples really helped. Last night I played with using a for loop instead of a while loop and got it working, but your examples really clarified things. This loop was particularly interesting because I didn't know the else could be attached to the for. Attaching it to the for solved a lot of problems. for letter in avoid: if letter in word: break else: print word I've printed out this whole thread and will be playing with your and others' solutions. I love this one for its conciseness, but will have to play with it to get my head around it. if not any(letter in word for letter in avoid): print word Thanks again. takayuki -- http://mail.python.org/mailman/listinfo/python-list takayuki, Could you post the complete script. thanks david -- Powered by Gentoo GNU/LINUX http://www.linuxcrazy.com Jun 27 '08 #16

 P: n/a En Mon, 16 Jun 2008 22:51:30 -0300, John Salerno I'm early on in my python adventure so I'm not there yet on the stripcommand nuances. I'm reading "How to think like a pythonprogrammer" first. It's great.Then "Learning python". I've read parts of Dive into Python and willwork through it fully when I'm a little farther along. Yeah, I really recommend Learning Python for getting the basics first. It's very thorough in that regard. Dive Into Python is *not* for beginners. I'm sorry if people disagree, but it's just not. Sure, the author himself says so at the very beginning in http://www.diveintopython.org "Dive Into Python is a Python book for experienced programmers." -- Gabriel Genellina Jun 27 '08 #17

 P: n/a Gabriel Genellina wrote: En Mon, 16 Jun 2008 22:51:30 -0300, John Salerno takayuki wrote: >>I'm early on in my python adventure so I'm not there yet on the stripcommand nuances. I'm reading "How to think like a pythonprogrammer" first. It's great.Then "Learning python". I've read parts of Dive into Python and willwork through it fully when I'm a little farther along. Yeah, I really recommend Learning Python for getting the basics first.It's very thorough in that regard. Dive Into Python is *not* forbeginners. I'm sorry if people disagree, but it's just not. Sure, the author himself says so at the very beginning in http://www.diveintopython.org "Dive Into Python is a Python book for experienced programmers." I know, but I just hear so many people recommend that book for people who want to learn the language. Jun 27 '08 #18

### This discussion thread is closed

Replies have been disabled for this discussion.