Newbie trying to learn some basic python, I've imported a json file containing a dictionary of terms. I'm trying to create a script that lets users look up definitions from my dictionary. I'm getting stuck on lines 14-15. I don't want the script to stop after just two attempts. I can work out how to set it to a max # of attempts but not how to make it infinite allowing unlimited tries. Each new query should be followed by a close match result using the get_close_matches method in difflib if the attempt is not an exact match, with the user prompted to accept or reject the closest match. My script, however, will stop after two attempts and if the 2nd query is not an exact match error out instead of presenting the 3 (the default for the method) closest matches to the word. Any ideas?
import json
from difflib import get_close_matches
data=json.load(open('data.json'))
def translate(w):
w=w.lower()
if w in data:
return data[w]
elif len(get_close_matches(w,data.keys()))>0:
yn=input("Did you mean %s? Enter Y or N: " % get_close_matches(w,data.keys())[0]).upper()
while yn =="N":
i=input("Enter Word: ")
return data[get_close_matches(i,data.keys())]
else:
return data[get_close_matches(w,data.keys())[0]]
word=input("Enter Word: ")
print(translate(word))
Your current approach isn't working because of the return statement inside the while yn == "N" loop. That return immediately takes you out of the function, regardless of whether the loop has completed, so there's no way for this loop to run more than once.
You could edit the loop to prevent it from always returning, but it's easier to move the loop outside the function. That way you don't have to worry about whether you're working with the initial input or a subsequent input, and you can cut down on duplicate code:
def translate():
w = input("Enter Word: ").lower()
if w in data:
return data[w]
close_matches = get_close_matches(w, data.keys()) # This only runs if w was NOT in data
if len(close_matches) > 0:
yn = input("Did you mean %s? Enter Y or N: " % close_matches[0]).upper()
if yn == 'Y':
return data[close_matches[0]]
return None # This is optional. Reaching the end of a function will return None by default
translated_word = None # Force at least one iteration of the loop
while translated_word is None: # Keep going until there's a match or the user types "Y"
translated_word = translate()
print(translated_word) # This will only run once the loop condition is False
Related
I'm trying to create a "football" game on python and if the user wants to pass the ball, my code is supposed to have a 50% probability of having an incomplete pass or a completion yielding between 3 and 15 yards
I know that to print the yardage, the code would look something like
import random
input("Enter r to run and p to pass")
p = print(random.randint(3,15))
but I'm not sure how to make "Incomplete" show up as a 50% probabilty
You can use the code below. As you have defined a statement to pick a random number between 3-15, you can create another statement to pick 0 or 1 (not %50 guaranteed). Also in your code, you are assigning return value of the print function to a parameter. This is definitely wrong! Print function returns nothing so assigning it to another variable is meaningless.
x = random.randint(0,1)
if x == 1:
random.randint(3,15)
else:
# incomplete pass
You could use something like this.
import random
inp = input("Enter r to run and p to pass")
if(inp == "p"):
print(random.choice([random.randint(3,15),0]))
elif(inp == "r"):
print("ran successfully")
This: random.choice([random.randint(3,15),0]) is the important bit. random.choice takes multiple values (in this case 2) in a list, and picks one randomly (2 values => 50% probability).
I also fixed the input output thing. To get input from the user you assign the value of input to a variable like this: example = input("Your input here: "). If you ran that line of code, and answered with potato for instance, you'd be able to print example and get potato (or whatever the user answered) back.
If you'd like to really flesh your game out, I'd suggest looking into template strings. Those let you do wonderful things like this:
import random
inp = input("Enter r to run and p to pass")
if(inp == "p"):
print(random.choice([f"Successfully passed the ball {random.randint(3,15)} yards","You tripped, the ball wasn't passed."]))
elif(inp == "r"):
print("Ran successfully.")
So, for context I am trying to write a script that checks a text input fulfils all of the necessary requirements for a username.
However, the section I wrote to repeat the function if the conditions are not met always repeats after the first attempt even if the conditions are met. The first attempt works as intended.
This is the section that uses a list of conditions not met to establish whether or not to repeat the function, however even when the username is correct it repeats if after the first attempt.
if error_stack != []:
repeat = True
else:
repeat = False
return repeat
repeat = username_input(input("Please enter a username with only numbers and letters, which is above 2 characters and below 15 characters. If the username is taken you will be asked to pick a new one. \n|:"))
print(repeat) #please help its always true.....
while repeat == True:
repeat = username_input(input("Please enter a username with only numbers and letters, which is above 2 characters and below 15 characters. If the username is taken you will be asked to pick a new one. \n|:"))
print(repeat) #please help its always true.....
if __name__ == "__main__":
main()
In this screenshot I input 1 username which should result in the control var being set to True and the loop repeating, then I input 1 username which should result in the control var being set to False and the loop not repeating.
2 inputs 1 works other doesnt
In this screenshot I input 1 user name which should result in the control var being set to False and the loop not repeating. It then works as intended.
1 input works
Can someone please explain to me why the condition only functions as it should (as far as I'm aware it should check if the condition is met every time the loop ends after the first time) the first time, then after refuses to exit?
Edit: Full code of section
import os
STANDARD_CHARS = list("abcdefghijklmnopqrstuvwxyz1234567890 ")
ERROR_DICT = {
"NonStandardCharacterError":"Your username should only have letters and numbers in it, please pick another.",
"CurrentUserError":"Your username has already been taken, please pick another.",
"LengthError":"Your username should be more than 2 characters in length, and fewer than 15 characters in length, please pick another.",
}
def main():
printed_errors = []
error_stack = []
current_users = []
def username_input(word_input):
for char in list(word_input.lower()):
if char not in STANDARD_CHARS:
error_stack.append("NonStandardCharacterError")
if word_input.lower() in current_users:
error_stack.append("CurrentUserError")
if len(word_input) > 15 or len(word_input) < 3:
error_stack.append("LengthError")
for error in error_stack:
try:
if error not in printed_errors:
print(ERROR_DICT[error])
printed_errors.append(error)
except KeyError:
print("Your username has thrown an unknown error , please try again later or pick another username.")
if error_stack != []:
repeat = True
else:
repeat = False
return repeat
repeat = username_input(input("Please enter a username with only numbers and letters, which is above 2 characters and below 15 characters. If the username is taken you will be asked to pick a new one. \n|:"))
print(repeat)
while repeat == True:
repeat = username_input(input("Please enter a username with only numbers and letters, which is above 2 characters and below 15 characters. If the username is taken you will be asked to pick a new one. \n|:"))
print(repeat)
if __name__ == "__main__":
main()
You initialize error_stack to [] in main, and append to it in username_input. But after its initial creation, you never reset it back to the empty list. So error_stack grows and grows, retaining old errors even when the user enters valid input.
Try creating error_stack inside username_input instead of inside main. Then it will be set to the empty list for every new user input prompt.
def main():
printed_errors = []
current_users = []
def username_input(word_input):
error_stack = []
for char in list(word_input.lower()):
#...
If, for some reason, it is necessary to keep error_stack in the higher scope, you can instead clear it with the clear method.
def main():
printed_errors = []
error_stack = []
current_users = []
def username_input(word_input):
error_stack.clear()
for char in list(word_input.lower()):
#...
My question is about getting a user to pull and item from a list. If the item from the list isn't pulled from the list I want to tell the user that he is incorrect. So my code looks like this:
Body_Type = ['Large', 'Medium', 'Small']
print('Create a Character-')
print('Body Type Choices: ' + str(Body_Type))
bt = input('Enter your Body Type: ')
while bt != Body_Type:
if bt == Body_Type[0:]:
print('Your Body Type is: ' + bt)
else:
print('Invalid Body Type')
What I'm trying to do is make my user create a character. This is just the first part of my first simple project. I want to have him pull from one of the items on the list, being "Large, Medium, Small" respectively. I want it to repeat until the user chooses one of the three. I tried to use or but it seems to feel unorganized and I'd have to break up the list and assign each individual variable.
Thanks in advance!
Several errors here like comparing a string to a list, or random slicing hoping that it would work. And the fact that your input statement is before the loop creates an infinite loop because you're comparing 2 variables of a different type again and again (bt != Body_Type is always True regardless of the content of bt since left hand is a string, right hand is a list).
But it shouldn't be so complex to write some working code.
I would create an infinite loop and break only if choice is in the list:
while True:
bt = input('Enter your Body Type: ')
if bt in Body_Type:
print('Your Body Type is: ' + bt)
break
else:
print('Invalid Body Type')
simpler and clearer (and repeats input if fails). The infinite loop (with an always true condition) allows to avoid double input call & test. Just loop, input the string, and break from the loop if matches.
The key statement you were looking for was bt in Body_Type which tests if the string is within the list.
I am trying to solve some problems in CodeAbbey using Python.I have run into a wall trying to take input for these programs.I have spent so much time analyzing how to take the input data without even solving the question.Hope someone explains how to take input.
Problem:I have to input the following numbers in One go. I have tried using 'input()' but it takes only one line. Is there any work around to do it in a simple way? i wasted so much time trying to analyse various options
632765 235464
985085 255238
621913 476248
312397 751031
894568 239825
702556 754421
474681 144592
You can find the exact question here: http://www.codeabbey.com/index/task_view/sums-in-loop
You can just repeat input() until you get all your data, e.g.:
try:
input = raw_input # fix for Python 2.x compatibility
except NameError:
pass
def input_pairs(count):
pairs = [] # list to populate with user input
print("Please input {} number pairs separated by space on each new line:".format(count))
while count > 0: # repeat until we get the `count` number of pairs
success = True # marks if the input was successful or not
try:
candidate = input() # get the input from user
if candidate: # if there was some input...
# split the input by whitespace (default for `split()`) and convert
# the pairs to integers. If you need floats you can use float(x) instead
current_pair = [int(x) for x in candidate.split()]
if len(current_pair) == 2: # if the input is a valid pair
pairs.append(current_pair) # add the pair to our `pairs` list
else:
success = False # input wasn't a pair, mark it as unsuccessful
else:
success = False # there wasn't any input, mark it as unsuccessful
except (EOFError, ValueError, TypeError): # if any of the conversions above fail
success = False # mark the input as unsuccessful
if success: # if the input was successful...
count -= 1 # reduce the count of inputs by one
else: # otherwise...
print("Invalid input, try again.") # print error
return pairs # return our populated list of pairs
Then you can call it whenever you need number pairs like:
my_pairs = input_pairs(7) # gets you a list of pairs (lists) entered by user
My first attempt would be to try a typing like "632765 235464\n985085 255238[...]" so you could read it as one line. This would be pretty hacky and not a good idea if its real userinput.
The other idea: Why not taking the input line by line and putting these lines in a list / appending them to a string?
EDIT:
I found some Code on SO, but its python2.7 i guess. ->Here
The Python3.X style would be:
#!/usr/bin/python
input_list = []
while True: # Infinite loop, left by userinput
input_str = input(">") #The beginning of each line.
if input_str == ".": #Userinput ends with the . as input
break # Leave the infinite loop
else:
input_list.append(input_str) #userinput added to list
for line in input_list: #print the input to stdout
print(line)
Hope this will help :)
Pretty new to python/programming in general, this is my biggest project yet.
I am writing a program that will do SUVAT equations for you. (SUVAT equations are used to find the displacement, start/end velocity, acceleration and time travelled by an object with constant velocity, you may call them something different.)
I made this list:
variables = ["Displacement", "Start Velocity", "End Velocity", "Acceleration", "Time"]
which is used in the following while/for loop:
a = 0
while a==0:
for variable in variables:
# choice1 is what the user is looking to calculate
choice1 = raw_input("Welcome to Mattin's SVUVAT Simulator! Choose the value you are trying to find. You can pick from " + str(variables))
# will execute the following code when the for loop reaches an item that matches the raw_input
if choice1 == variable:
print "You chave chosen", choice1
variables.remove(variable) #Removes the chosen variable from the list, so the new list can be used later on
a = 1 # Ends the for loop by making the while loop false
# This part is so that the error message will not show when the raw_input does not match with the 4 items in the list the user has not chosen
else:
if choice1 == "Displacement":
pass
elif choice1 == "Start Velocity":
pass
elif choice1 == "End Velocity":
pass
elif choice1 == "Acceleration":
pass
# This error message will show if the input did not match any item in the list
else:
print "Sorry, I didn't understand that, try again. Make sure your spelling is correct (Case Sensitive), and that you did not inlcude the quotation marks."
Hopefully the comments I have written in the code should explain my intentions, if not, feel free to ask anything.
The problem is that when I run the code, and input choice1, the for loop activates the last line of code:
else:
print "Sorry, I didn't understand that, try again. Make sure your spelling is correct (Case Sensitive), and that you did not inlcude the quotation marks."
and then prompts me to enter the input again, and will do this as many times as it needs to get to the item on the list that I am typing.
However, I specifically coded that if what I input does not match the item on the list the for loop is currently checking, but does match one of the other items on the list, then it should pass and loop round to checking the next item.
I am probably doing something stupid, but I don't see it, so please help me figure out what I have to do to get my desired result? I assumed it was the syntax I had wrong so that is why that is the title.
Thanks for any help, I appreciate it.
Besides the problem with the indentation in your pasted code, I would rewrite it as such:
while True:
choice = raw_input('...')
if choice in variables:
print "You chave chosen", choice
# Remove the chosen member from the list
variables = [v for v in variables if v != choice]
# Break out of loop
break
# Print error messages etc.
Also remember that string comparisons are case sensitive. I.e 'Displacement' != 'displacement'.