Best alternative to using if statement? - python

I am trying to break out of a bad habit of using if/else too frequently. I am new to how functions work and the proper way to call them but I am constantly researching the correct way to implement them with my code. The code that I am making is suppose to check for 3 different words and if the word is not in the input then the user will receive a statement that says "rejected" if the word is correct it will say "accepted". The issue that I am facing is getting my program to work correctly. So far I have set up my program to check each index of the word and if it matches the full word it will be marked as accepted. I am trying to figure out the correct way to add a rejected flag and to avoid the error that I recieve after running this program.
def checker():
q0 = input("enter word:")
if (q0[0]) +(q0[1]) == "if":
print ("accepted")
if (q0[0]) + (q0[1]) + (q0[2]) + q0[3] == "else":
print("accepted")
if(q0[0]) + (q0[1]) == "do":
print("accepted")
else:
print("rejected")
checker()
For this program, I am not going to use a dictionary so I can correctly challenge myself and implement this in an automata fashion. How can I implement this code without getting the string index out of range error. I tried to put break after my print statement but it doesn't work.
Thanks in advance to everyone. This is my first post so if I have made any mistakes in my post please let me know!

Here's an extensible one-liner for you:
def check():
q = input().strip()
acceptable = {'if', 'else', 'do'}
print('accepted' if q in acceptable else 'rejected')
The variable acceptable is set; a data structure which is very quick to check if something is inside of it. You can modify this set (or pass it to check as an argument!) to change the range of acceptable words without changing the control flow of the program (as you would in your original if/else implementation that you're laudably trying to move away from).
EDIT: I guess it's not strictly a 'one-liner'...

First, why do you access each character of the input string, then concatenate them again, then compare to a target string("if", "else", "do")?
Second, why do you use if statements repeatedly if matching either one of them will lead to the same result (print("accepted")?
Try this:
def checker():
q0 = input("enter word:")
if q0 in ["if", "else", "do"]:
print("accepted")
else:
print("rejected")
checker()
Now, you just compare a string q0 to another (each element of the list ["if", "else", "do"]). Also, the first hit in the list will make stop comparing anymore and will continue on to print "accepted".
++ Just to let you know why are you seeing "index out of range error", you are accessing each character of q0 without knowing how many there are. So if the user inputs a string like a, there's no q0[1] or q0[2], but you're asking your program to access it. Thus index out of range error.

You can do this with a for loop and one if statement if that is better for you. Simply put all the accepted values into a list and check if each word is in q0.
def checker():
q0 = input('enter word:')
for i in ['if', 'else', 'do']:
result = ('accepted' if i in q0 else 'rejected')
if result == 'accepted':
break
print(result)

you can do it as one liner with lambda function.
checker = lambda q: print("accepted" if q in ["elif", "if", "else"] else "rejected")
checker()
here is a sample
>>> checker = lambda q: print("accepted" if q in ["elif", "if", "else"] else
"rejected")
>>> checker("if")
accepted
>>> checker("fool")
rejected

Related

How to remove only one instance of specified character in string

If I have a list of strings such as the following:
"apple.test.banana", "test.example","example.example.test".
Is there a way to return only "test.banana" and "example.test"?
I need to check and see if there are two dots, and if there are, return only the value described above.
I attempted to use:
string="apple.test.banana"
dot_count=0
for i in string:
if i==".":
dot_count=dot_count+1
if dot_count>1:
string.split(".")[1]
But this appears to only return the string "test".
Any advice would be greatly appreciated. Thank you.
You are completely right, except for the last line, which sould say '.'.join(string.split(".")[1:]).
Also, instead of the for loop, you can just use .count(): dot_count = string.count('.') (this doesn't affect anything, just makes your code easier to read)
So the program becomes:
string = "apple.test.banana"
dot_count = string.count('.')
if dot_count > 1:
print('.'.join(string.split(".")[1:]))
Which outputs: test.banana

python, loops: searching against a list to see if item is present, appending to new list

I am trying to make a program where my students will enter their ID numbers so I can (later in the code) automate sending attendance, and record who has handed in homework and who hasn't so emails can be sent to parents. I have everything else made, but I cannot get the inputting of student ID's working.
What I am trying to do:
1)make sure that their input is 7 characters long
2)check their ID exists in 'fakeID'
2a)have the students confirm their name from 'classNames' with a y/n.
2b) append their name into inputIDList
3) if the input is == to 9999990 exit the loop.
What it is doing:
1) asking for input
2) moving on in the code and not looping
3) not appending inputIDList
I think I am making this too complicated for my current skill level.
edit:
The loop is not checking to see if the inputed ID is in my fakeID list.
Also, it isnt looping for, so once the input is entered it continues on with the next set of code.
edit2:
updated code that works. :D
fakeID = ['1111111','1111112','1111113','1111114','1111115']
classNames = ['name1', 'name2', 'name3', 'name4', 'name5']
toplist = list(zip(fakeID, classNames))
inputIDList =[]
def inputID():
while True:
id = input('Please enter your student ID and hit Enter')
if id == '9999990':
print('Done')
break
if id in fakeID:
inputIDList.append(id)
print('recorder')
continue
if id not in fakeID:
print('I do not know this ID. Please try again.')
continue
If I understood your problem correctly then I suppose that you are trying to save the ID numbers of the students in inputIdList and then check whether a particular ID is in inputIdList or not. In the last if condition you are trying to compare a List type object with a String type object which will definitely throw an TypeError. Instead define the following function and call it in the if condition.
def check_list(id):
try:
inputIdList.index(id)
return True
except TypeError:
return False
list.index() method tries to find the element in the list and returns the index number of the element. And then call this function in your if condition.
if check_list('9999990'):
print('done')
#break
Furthermore there is no need to assign inputIdList = [""] if you have already intialized it to inputIdList = [].
If the problem persists please send the output in the thread.
Here is something to get you started:
fakeID = {'1111111','1111112','1111113','1111114','1111115'}
while True:
id = input('Please enter your student ID and hit Enter')
if id == '9999990':
print('Done')
break
if id not in fakeID:
print('I do not know this ID. Please try again.')
continue
as Abarnert said you need to restructure your method. but I think I found where you were stuck.
after you have checked for the length of input number, you should check whether that number matches any fakeID,and get the corresponding class name.
so your first loop should be like this
for i in toplist:
rather than
for i in [i for i,x in enumerate(inputIDList) if x == fakeID]:
since inputIDList is empty your program will not go inside the loop. And inside the changed loop you should be checking
if s == fakeID
This is the limit of what I could understand of your desired operation. But if you need further help just ask.
cheers.

How to make an if statement using widget option values as conditions?

Let's say i have a this button:
tl.config(bd=0 ,image=photo1 ,width="100",height="100",command=lambda: functionPlus(tl))
The function is :
def functionPlus(button):
global turn
if (turn==1 or turn==3 or turn==5 or turn==7 or turn==9):
button.config(image=photo2,width="100",height="100")
turn +=1
elif (turn==2 or turn==4 or turn==6 or turn==8) :
button.config(image=photo3,width="100",height="100")
turn+=1
I would like to add an 'if' in the function, that would have as condition the image of the button. For exemple :
if button.config(image=photo2 == True) :
anotherFunction()
Thanks in advance.
First, never use the expression pattern something=something else == True!
Second, take a look at this related (but not duplicate) question.
As you can see there, the cget method will return the current value for an option. As this manual page mentions, cget is analogous to widget["option"].
So, to answer your question directly, the if condition you need would be along the lines of:
if button['image']==photo2:
anotherFunction()
I'm new here and couldn't comment. I hope I'm not flaunting SO policy by resorting to answering instead.
#Tersosauros
"First, never use the expression pattern something=something else ==
True!"
Where do you see this pattern and why should it be avoided? What could replace it? (I know you're a tersosaurus but "never use X" just seems TOO terse and uninformative).
#Arwan Credoz I know you got your answer but... If you simply want to check whether the value of "turn" is a an even/odd number and is within a given range, use a bounds check followed by modulus instead (maybe this is what #Tersosauros was hinting at?).
Also, the value of "turn" will always be incremented if it's within range(0,10) so there's no need to write "turn+=1" twice. If I've understood your intentions correctly, you could probably rewrite "functionPlus" to something like this and add Tersosaurus' addition where appropriate:
def functionPlus(button):
global turn
if 0 < turn < 10:
if turn % 2 == 0:
button.config(image=photo3,width="100",height="100")
else:
button.config(image=photo2,width="100",height="100")
turn += 1

Python skipping some lines in for loop

I've got a script I'm writing, and have a function that should search a dictionary with this layout:
{
1 : ['name1','name2','name3','name4','name5'],
2 : ['name1','name2','name3','name4','name5']
}
for a word. Here's the function:
def find_student(list_curr):
''' (str, dict) -> list
Input is the student's name and the dictionary of lists that they should exist in; output is a list in the format:
[group,index]
'''
while True:
try:
stu_name = input("\nPlease enter the first or last name of the student, or press enter to exit:\n> ")
if not stu_name:
return False
else:
break
except ValueError:
print("Please enter a valid name")
for g,s in list_curr.items():
print("G",g)
print("S",s)
if any(stu_name in n for n in s):
# name was in group
print("\nFound a possible match: {} (group {}):".format(s[s.index(stu_name)],g))
pp.pprint(s)
if input("\nIs this the student you're looking for?\n> ") in "yesYES":
# found the correct student
print("Saving {} for group and {} for index.".format(g,s.index(stu_name)))
stu_info = [g,s.index(stu_name)]
return stu_info
# nothing was found
print("\n{} was not found in the list.".format(stu_name))
return False
When I run it, though, it breaks as soon as it finds a match. Everything below the if any(): part is not run, and it just returns without even printing the Found a possible match... line. I've tried using the debugger in IDLE but it continually crashes whenever I open it. I've seen other posts really similar to this, but don't understand where I'm going wrong. Any ideas?
Edit: sorry, had for any(), should be if any().
You may be getting a ValueError on
if any(stu_name in n for n in s):
# name was in group
print("\nFound a possible match: {} (group {}):".format(s[s.index(stu_name)],g))
any(stu_name in n for n in s) checks if stu_name occurs as a substring of a string in list s.
The s.index(stu_name) however tries to find the index of an exact match between stu_name and the elements within s.
Try substituting example values to see what's going on:
s = ['James Joyce', 'Tom Stoppard', 'William Shakespeare']
stu_name = 'William'
print(any(stu_name in name for name in s))
print(s.index(stu_name))
Not sure why you're not seeing an Exception, perhaps there's a naked Except clause somewhere else in your code?
If the above issue is your problem, maybe write an inline function like this within find_student:
def get_index(stu_name, names):
for index, name in enumerate(names):
if stu_name in name:
return index
and call get_index(stu_name, s) instead of s.index(stu_names).
Alternatively, maybe you just want to edit your code so that you only accept exact matches.
In which case,
if any(stu_name in name for name in s):
becomes
if stu_name in s:
And the user needs to enter "William Shakespeare" instead of just "William".
P.S. This isn't what was asked for in the op, but...
What happens if there are multiple people with the inputted first/last name in the same group? As I see it, it looks like the script will only give the user the option to choose the index of the first match, and if the user says this isn't the student in question, the script starts looking at the next group, rather than returning the next index within the same group.

Local variable 'list' referenced before assignment

I made a simple script that converts any input text into a "code" and can also translate it back. It only works one word at a time.
I want to make the script adds each new code to a list that is printed every time. For example, the first time you translate something, "HELLO" becomes "lohleci". The second time, I want it not only to show "world" = "ldwropx", but also state below everything translated so far.
I'm new to Python and have looked through forums for people with similar problems. The way I tried doing it (a segment was removed and put into a separate script), I get an error saying "local variable 'list' referenced before assignment." This is the code producing the error:
list = "none"
def list():
word = raw_input("")
if list == "none":
list = word + " "
print list
list()
else:
new_list = list + word + " "
list = new_list
print list
list()
list()
Your code has several problems, all of which are fixable with a bit more knowledge.
Don't use the name list for your own variables or functions. It's the name of a built-in Python function, and if you use that name for your own functions you won't be able to call the built-in function. (At least, not without resorting to advanced tricks which you shouldn't be trying to learn yet.)
You're also re-using the same name (list) for two different things, a variable and a function. Don't do that; give them different, meaningful names which reflect what they are. E.g., wordlist for the variable that contains a list of words, and get_words() for your function.
Instead of using a variable named list where you accumulate a set of strings, but which isn't actually a Python list, why not use a real Python list? They're designed for exactly what you want to do.
You use Python lists like this:
wordlist = []
# To add words at the end of the list:
wordlist.append("hello")
# To print the list in format ["word", "word 2", "word 3"]:
print wordlist
# To put a single space between each item of the list, then print it:
print " ".join(wordlist)
# To put a comma-and-space between each item of the list, then print it:
print ", ".join(wordlist)
Don't worry too much about the join() function, and why the separator (the string that goes between the list items) comes before the join(), just yet. That gets into classes, instances, and methods, which you'll learn later. For now, focus on using lists properly.
Also, if you use lists properly, you'll have no need for that if list == "none" check you're doing, because you can append() to an empty list just as well as to a list with contents. So your code would become:
Example A
wordlist = []
def translate_this(word):
# Define this however you like
return word
def get_words():
word = raw_input("")
translated_word = translate_this(word)
wordlist.append(translated_word)
print " ".join(wordlist)
# Or: print ", ".join(wordlist)
get_words()
get_words()
Now there's one more change I'd suggest making. Instead of calling your function at the end every time, use a while loop. The condition of the while loop can be anything you like; in particular, if you make the condition to be the Python value True, then the loop will never exit and keep on looping forever, like so:
Example B
wordlist = []
def translate_this(word):
# Define this however you like
return word
def get_words():
while True:
word = raw_input("")
translated_word = translate_this(word)
wordlist.append(translated_word)
print " ".join(wordlist)
# Or: print ", ".join(wordlist)
get_words()
Finally, if you want to get out of a loop (any loop, not just an infinite loop) early, you can use the break statement:
Example C
wordlist = []
def translate_this(word):
# Define this however you like
return word
def get_words():
while True:
word = raw_input("")
if word == "quit":
break
translated_word = translate_this(word)
wordlist.append(translated_word)
print " ".join(wordlist)
# Or: print ", ".join(wordlist)
get_words()
That should solve most of your problems so far. If you have any questions about how any of this code works, let me know.

Categories

Resources