What happens when loop gets to the end? - python

I am python beginner, with no previous programming knowledge. I apologize for the name of the topic, but I simply could not make a better one.
Here is what I want:
letter = "w" # search for this letter in the list bellow
listL = ["z","b","y","a","c"]
for let in listL:
if let == letter:
print "found it"
break
else:
if let == listL[-1]:
print "nope can't find it"
continue
I have a list of letters, and I want to search for a particular letter in that list.
If I find the letter, then everything is ok, and the for loop should stop.
If I do not find it, I would like the loop to stop that current iteration, and try with the next letter in the list. If not a single letter in the list has that particular letter, then it should print "nope can't find it".
The upper code works. But I was wondering if this could be wrote a bit clearly? And by clearly I do not mean "advanced", but scholar way, an-example-from-the-book way.
Thank you.

Python offers an else statement for the for loop that is executed if the loop ends without being broken:
for let in llistL:
if let == letter:
print("Found it!")
break
else:
print("nope could'nt find it")
That would be the "scholar way" for a for loop, however if you just test the presence of an element in a list, Arkady's answer is the one to follow.

How about just:
if letter in listL:
print "found it"
else:
print "nope..."

Simply use in
if let in listL:
print("Found it")
else:
print("Not found")
edit : you were faster by 30 s, congrats ;)

Your loop will keep looping until it either breaks (found it!) or the list is exhausted. You do not need to do anything special to "stop that current iteration, and try with the next letter in the list". We don't need a continue when a letter doesn't match, this will happen automatically as long as there are more letters to check.
We only want to display "nope can't find it" after we've searched through the entire list, so we don't need to check until the end. This else statement corresponds to the for loop, instead of the if in your previous code.
letter = "w" # search for this letter in the list bellow
listL = ["z","b","y","a","c"]
for let in listL:
if let == letter:
print "found it"
break #found letter stop search
else: #loop is done, didn't find matching letter in all of list
print "nope can't find it"

There is actually a for: else: construct in Python, where the else runs if the for loop doesn't break:
for let in listL:
if let == letter:
print("Found it")
break
else:
print("Not found")
Alternatively, you can use list.index, which will give the index of an item if found in a list and raise a ValueError if it isn't found:
try:
index = listL.index(letter)
except ValueError:
print("Not found")
else:
print("Found it")

Related

Why is this if statement broken in python?

I am attempting to make a 'simple' hangman game in python, but this if statement seems to not believe answer is == to guess, even when it clearly is... Thanks for any help :)
import random
guessed = False
file = open("hangmanwords.txt")
answer = file.readlines()[random.randint(0, 212)]
print(answer)
print("_ "*(len(answer)-1),"\n")
for counter in range(0,6):
guess = input("Enter your guess:\n")
if guess == answer:
break
else:
print("Unlucky, try again")
if counter == 5:
print("Unlucky, you did not guess it correctly. The correct word was",answer)
else:
print("Well done, you got it!")
The lines returned by readlines end in a newline (except, potentially, the last line).
In your case, you don't want that. You can use str.strip() to remove whitespace (including newlines) from the beginning and end of a string.
You can also use random.choice to select a random word. Which is useful if you later want to add or remove words without changing the code!
Also, you don't need to hardcode the number of tries if you use the for-else construct.
import random
with open("hangmanwords.txt") as file:
answer = random.choice([line.strip() for line in file if line and not line.isspace()])
print(answer)
print("_ " * len(answer))
for counter in range(6):
guess = input("Enter your guess:\n")
if guess == answer:
print("Well done, you got it!")
break
else:
print("Unlucky, try again")
else:
print("Unlucky, you did not guess it correctly. The correct word was", answer)

I need advice with while loop in python

I'm using python3 on mac.
I'm currently doing a project. However, I was trying to use "while = True" to continuously use the program until a condition is met. Please, tell me what am I missing in my code. Thanks!
import json
import difflib
from difflib import get_close_matches
data = json.load(open("project1/data.json"))
word = input("Enter a word or enter 'END' to quit: ")
def keyword(word):
word = word.lower()
while type(word) == str:
if word in data:
return data[word]
elif word == 'END'.lower():
break
elif len(get_close_matches(word, data.keys())) > 0:
correction = input("Did you mean %s insted? Enter Yes of No: " % get_close_matches(word, data.keys())[0])
if correction == "Yes".lower():
return data[get_close_matches(word, data.keys())[0]]
elif correction == "No".lower():
return "This word doesn't exist. Plese enter again. "
else:
return "Please enter 'Yes' or 'No: "
else:
return "This word doesn't exist. Please enter again."
print("Thanks!")
output = (keyword(word))
if type(output) == list:
for item in output:
print(item)
else:
print(output)
I think this might be the setup you are looking for.
def keyword(word):
if word in data:
return data[word]
elif len(get_close_matches(word, data.keys())):
correction = input(f"Did you mean {get_close_matches(word, data.keys())[0]} instead? y/n: ")
if correction == 'y':
return data[get_close_matches(word, data.keys())[0]]
elif correction == 'n':
return "This word doesn't exist. Please enter again."
else:
return "Please type 'y' or 'n': "
else:
return "This word doesn't exist. Please enter again."
while True:
word = input("Enter a word: ").lower()
if word == 'end':
print("Thanks!")
break
else:
print(keyword(word))
Looking at the source code and your question, it seems like what you want to achieve is basically to continuously accept input from the user until the user enters something like 'end'. One way to go about this is to separate out the while-loop logic from the function. The overarching while-loop logic is at the bottom half of the code, where we continuously accept input from the user until the user inputs some lower or upper case variant of 'end'. If this condition is not met, we proceed to printing out the result of the function call keyword(word).
Minimal modifications were made to the original keyword() function, but here are a few changes worthy of note:
The while type(word) == str is unnecessary, since the result stored from the input() function will always be a string. In other words, the condition will always return True.
Having return statements within a while loop defeats the purpose of a loop, since the loop will only be executed once. After returning the specified value, the function will exit out of the loop. This is why we need to separate out the loop logic from the function.
Although %s works, it's a relic of C. This might be a matter of personal choice, but I find f-strings to be much more pythonic.
You are using the worng condition.
type((3,4))== list
is False. You must use
type((3,4)) == tuple

Syntax error python, not sure how to write the code

I am trying to write a code that tests a word to see if it is a palindrome or not. It is working but it prints NO in a loop before it gives the correct answer. I want it to just print the correct answer once.
I haven't really done anything, just checked the internet for some answers
x = str(input("enter the word:"))
w = ""
for i in x:
w = i + w
if x == w:
print("YES")
else:
print("NO")
It should print YES or NO once, now it prints many times before giving the correct answer.
indent the w= i + w line
x = str(input("enter the word:"))
w = ""
for i in x:
w = i + w
if (x==w):
print("YES")
else:
print("NO")
Please correct your indentation to make it possible to trouble shoot.
At first glance it appears your “if” statement is nested in side your “for” loop, thus checking for the palindrome after each letter is added.
If you put the if else inside the loop, its bound to print the result multiple times. Keep it out of the loop and it will print just once.
Welcome to the Community!
A shorter way to do this could be:`
x = str(input("enter the word:"))
if (x==x[::-1]):
print("YES")
else:
print("NO")
You may want to look into string slicing in python :)
Mark B already solved your issue but here is an additional method out of interest.
word = input("Enter word")
reverse = word[::-1]
if word == reverse:
print("Yes, plaindrome")
else:
print("No, not palindrome")
Use your for loop to create a new string ( reverse of string x ). Use conditional outside the for loop. Also, check for uppercase entry.

when searching for a letter in a list, its gives me always two output or more. how do i fix this and what am i missing?

wordlist = ['a', 'b']
letters = ['l']
for item in wordlist:
for character in letters:
if character == item:
print ("found")
break
else:
if character != item:
print ("not found")
It gives me:
not found
not found.
I just want 1 not found as an output and not 2.
I think the rest speaks for itself? if not please feel free to ask.
You can declare a flag that imply whether you entered to the found section, if no, you break from the outer loop:
wordlist = ['a', 'b']
letters = ['l',"a"]
for item in wordlist:
found_flag = False
for character in letters:
if character == item:
found_flag = True
break
if found_flag:
print (item ,": found")
else:
print (item , ": not found")
break
Try this
i=0
for item in wordlist:
if item not in letters:
i+=1
if i > 0:
print "Not found"
Study your own code more carefully. Step through it yourself.
You are running the code for each item in wordlist. There are two of them and neither are matches, so it will print "not found" twice.
You don't need to write your own functions for this. There are many pre-written builtins to do simple things like this for you. Read the Python documentation about lists.

String Index Out Of Range (Python) I have made bounds too

import time
password=input("What's your password?")
ans = ""
password=password.lower()
alpha = "abcdefghijklmnopqrstuvwxyz"
n = 0
a=0
starttime=time.time()
while ans !=password:
print(a)
for i in range(len(password)):
letter=alpha[n]
ans+=letter
if ans[a] != password[a]:
print(ans)
ans = ans.replace(ans[a],"")
n+=1
break
else:
a+=1
print(ans)
n=0
break
print("Password Found!")
endtime=time.time()
time=endtime-starttime
print("It took " + str(time) + " seconds!")
This is my code, sorry if i'm not posting it right (first time here). But let's digress, It seems i get an error of string index out of range
Traceback (most recent call last):
File "C:\Users\admin\Documents\Letter word cracker.py", line 15, in <module>
if ans[a] != password[a]:
IndexError: string index out of range
I was wondering how to fix this, because its been eating at my brain for days. Any help would be appreciated, thanks!
Ok, I don't know why you are trying to do this, what you are trying to do, the error is here due to this line
ans = ans.replace(ans[a],"") ---> X
what replace will do, is replace all the occurrences of a particular character from the array, while you only need to remove the last.
For example :-
If ans = "naa",
now replace will replace both 'a' while based on your logic you only want to remove the last element. because you have already matched till "na" and now in process of matching the third element.
You could probably do :-
ans = ans[:-1]
But again, this is a very very bad way to do this, because strings are immutable so you are basically creating and destroying strings every iteration.
One advice I would give is using list of characters instead of a string, it would not give a significant boost to the runtime for your program, for whatever reason you are using this.
EDIT:-
Also the for loop is unnecessary, as it is always breaking after first iteration. thanks #TigerHawk
import time
password=input("What's your password?")
ans = []
password=password.lower()
alpha = "abcdefghijklmnopqrstuvwxyz"
n = 0
a=0
starttime=time.time()
while "".join(ans) !=password:
letter=alpha[n]
ans.append(letter)
if ans[a] != password[a]:
ans.pop()
n+=1
else:
a+=1
n=0
print("Password Found!")
endtime=time.time()
time=endtime-starttime
This is a little better and more condensed version. From what I understand, you want to brute force a character string to compare it to a password.
import time
password=input("What's your password?")
password=password.lower()
alpha = "abcdefghijklmnopqrstuvwxyz"
starttime=time.time()
for letter in range(len(password)):
for index in range(len(alpha)):
if alpha[index] == password[letter]:
print "Letter",letter,"Found."
next
print "Password Found!"
endtime=time.time()
time=endtime-starttime
print "It took",time,"seconds!"
There are a few issues per the previous post, but the IndexError is happening because you are comparing each element of each list, and when one list runs out, it raises the IndexError exception. Wrap that part of the code in an if() that checks to see whether there are any more elements left over.
This will not fix the entire program, and in fact, you'll likely need a better way to do this comparison... I'm just explaining why the IndexError is happening.
if (ans[a] and password[a]):
if ans[a] != password[a]:
print(ans)
ans = ans.replace(ans[a],"")
n+=1
break
You should really go through your logic to understand why it isn't working, but there are many improvements you can make to your code. I have implemented a working version with a few improvements below.
from time import time
import string
#this will only work for a-z no whitespace, caps, numbers, etc.
pwd = raw_input("What is your password? ")
pwd = pwd.lower()
#create list of password for easier iterability
password = list(pwd)
#alphabet will have a-z lowercase
alphabet = list(string.ascii_lowercase)
#empty list to start
guess = []
#start timer
start = time()
#outer loop through password
for char in password:
#inner loop through alphabet
for letter in alphabet:
if letter == char:
guess.append(letter)
break
#print correct guess as string
end = time()
print "It took " + str(end - start) + " seconds to solve this password."
#verify correctness
print "".join(guess)
print pwd

Categories