Why does my elif go back to my if? - python

I have written a very basic encryption program, and whilst writing the decrypting algorithm for it, I have encountered some problems with a loop I have.
from re import *
cipher = open('cipher.txt')
ciphertext = cipher.read()
keyfile = open('key.txt')
key = keyfile.read()
decoded = []
chardec = ''
inval = 1
print("Decoder for encrypt1.py")
while inval == 1:
useManKey = input("Use a manual key? Y or N\n> ")
if useManKey == 'Y' or 'y':
key = input("Please enter the key you wish to use to decrypt\n> ")
inval = 0
elif useManKey == 'N' or 'n':
inval = 0
print("OK, decrypting")
else:
print("That wasn't a valid option/nPlease re-enter")
When I run this, and declare useManKey as N or n it seems to run the if part of the loop as if I had declared it as Y or y. I am probably being stupid here, but any help would be much appreciated thanks.

useManKey == 'Y' or 'y' does not work how you think it does. What you want is useManKey in ('Y', 'y'). What you have first evaluates useManKey == 'Y', then, if that check fails, tests the string 'y' for truishness. Since non-empty strings are always truish, your if statement always evaluates to True. As is pointed out in the comments, you could also use upper() or lower() to first convert the input to a fixed case if you want.

useManKey == 'Y' or 'y'
Doesn't actually check whether useManKey value being 'Y' or 'y', Use sr2222's answer for what you need to do. ie.
useManKey in ('Y', 'y')
The earlier expression evaluates to
(useManKey == 'Y') or 'y'
Which is always True irrespective of the value of useManKey as 'y' being non-Falsy (non-None) the 'or' of these always evaluates to True,

Related

Python: Keyboard prompt with capital/noncapital letters

In this code:
if raw_input("\n Enter 'y' or 'Y': ")==("y" or "Y"):
print("\n Success!")
It doesn't take the "OR" properly, instead if the in this case noncapital 'y' is entered the condition is fulfilled. If I enter the capital 'Y' I don't get the Success!
What's wrong here?
Try this
if raw_input("\n Enter 'y' or 'Y': ").lower() == "y":
Try to make a list of values and use the in keyword. Something like this will work,
if raw_input("\n Enter 'y' or 'Y': ") in ('y', 'Y'):
print("\n Success!")
The in keyword tests the string against a tuple of strings and on a correct match it returns True.
Since here you have just one character, you can build a string "yY". Something like this will work,
if raw_input("\n Enter 'y' or 'Y': ") in "yY":
print("\n Success!")
Here each character of the string acts like one element of the tuple above.
ERROR in your code:
You used ("y" or "Y"). This does not work in Python. This will only return "y" as both "y" and "Y" are treated as True values. However, if you type (0 or "Y"), you will get "Y" as 0 is treated as a False value.
The right-hand-side of your if-statement is wrong and I think you need to understand a little better how the or operator behaves between strings.
Keep in mind that the return value of or is the value that has been evaluated last, and that Python evaluates empty string as boolean False and non-empty strings as boolean True.
In your case, the interpreter reads ("y" or "Y"), it then evaluates the boolean value of "y" which is True, as it is a non-empty string. Therefore, the boolean value of the or statement it True and the return value of the statement becomes "y", the last evaluated value.
This is how I would write this code. I would keep the return value of raw_input in _input, which will make it easier for me and others to read and understand the if-statement:
_input = raw_input("\n Enter 'y' or 'Y': ")
if input in ["y", "Y"]:
print("\n Success!")
What's wrong here?
In many programming languages, OR is a boolean operator. You apply it to values that are TRUE or FALSE. The operation evaluates to TRUE if at least one operand is TRUE:
TRUE OR TRUE == TRUE
TRUE OR FALSE == TRUE
FALSE OR TRUE == TRUE
FALSE OR FALSE == FALSE
In Python, you can apply or on non-boolean operands:
x or y
returns x if x casted to boolean is True; else it returns y. For boolean operands, this leads to the same results as above, but for non-boolean operands this has interesting effects:
[] or {} is {} (because empty lists are False when casted to
boolean)
[1] or {} is [1] (because non-empty lists are True when casted to boolean)
[1] or 1/0 is also [1] (the right operand doesn't even get evaluated when the left one is True, so we don't hit the ZeroDivisionError. This is known as (left-to-right) short-circuit evaluation.)
Thus, other than in natural language, the Python or cannot be interpreted as separating alternative values. (Only alternative conditions / boolean expressions.)
There are several possibilities on how to make your code behave as expected:
The naive approach:
answer = raw_input("\n Enter 'y' or 'Y': ")
if answer == "y" or answer == "Y":
print("\n Success!")
Normalizing the input:
if raw_input("\n Enter 'y' or 'Y': ").lower() == 'y':
print("\n Success!")
Comparing to set of alternative values with membership operator in:
if raw_input("\n Enter 'y' or 'Y': ") in {'y', 'Y'}:
print("\n Success!")

Python3 Skipping Flow Check [duplicate]

This question already has answers here:
How to test multiple variables for equality against a single value?
(31 answers)
Closed 6 years ago.
I'm having a bit of trouble with my python3 persistent password locker. It stores and retrieves passwords as expected/desired, but I decided to insert a "backout" check so that if information is entered incorrectly you can go back and re-enter it. It seems to be skipping this check for no easily identifiable reason.
elif choice == 2:
conti = False
while conti != True:
print('Enter an account and password to store')
acc = input('Account: ')
apass = input('Password: ')
print('Account: ' + acc + '\n' + 'Password: ' + apass)
print('Correct?')
corr = input(': ')
corr.lower()
if corr == 'yes' or 'ye' or 'y':
print('Making Changes persistent')
# Shelve Stuff
conti = True
break
else:
print('Please make appropriate changes.')
continue
When I run this code it makes changes persistent regardless of what the corr variable happens to be. This is not what I want. I tried explicitly stating in an elif statement the no options and it skipped those as well. Are the multiple 'or' statements throwing it off or is there something else going on that I should be aware of?
This line is not doing what you'd hoped:
if corr == 'yes' or 'y' or 'y':
This translates to "is corr equal to 'yes'? It's not! So, is the value 'y' True? It is! Let's do this!" Note, it's not checking that corr is equal to 'y', just that the string 'y' is Truthy.
The longhand way would be:
if corr == 'yes' or corr == 'y':
but you could also do:
if corr in ['yes', 'y', 'Y', 'YES']:
or something similar to cover more options

Python while loop with or not giving expeted output

This is my loop:
sure = input('Are you sure that you wish to reset the program?(y/n)')
while sure != 'y' or sure != 'n':
sure = input('Please awnser y or n, Are you sure that you wish to reset the program?(y/n)')
The loop carries on looping even if y or n are entered.
Change the condition to
while sure != 'y' and sure != 'n':
Your condition as written will always be True no matter what they enter. An alternative would be
while sure not in ('y','n'):
You need to do and instead of or . When doing or it will continue to the loop if sure is not y as well n , but sure cannot be both at the same time, hence it loops forever.
Example -
sure = input('Are you sure that you wish to reset the program?(y/n)')
while sure != 'y' and sure != 'n':
sure = input('Please awnser y or n, Are you sure that you wish to reset the program?(y/n)')
The problem is in your logical expression:
sure != 'y' or sure != 'n'
Using De Morgan's Law, this could be rephrased as:
!(sure == 'y' and sure == 'n')
Obviously, sure can never be both 'y' and 'n', so this doesn't work. What you want instead is:
sure != 'y' and sure != 'n'

python if statement evaluation with multiple values

I'm not exactly sure why but when I execute this section of code nothing happens.
while (True) :
choice = str(input("Do you want to draw a spirograph? (Y/N) "))
if choice == 'n' or 'N' :
break
elif choice == 'y' or 'Y' :
<CODE>
else :
print("Please enter a valid command.")
choice = input("Do you want to draw a spirograph? (Y/N)")
It won't work because the 'N' literal always evaluates to True within your if statement.
Your if condition currently stands as if choice == 'n' or 'N' :, which is equivalent to if (choice == 'n') or ('N'), which will always evaluate to True irrespective of the value of variable choice, since the literal 'N' always evaluates to True.
Instead, use one of the following
if choice == 'n' or choice == 'N' :
if choice in 'nN' :
if choice in ('n', 'N') :
The same holds for your elif block as well. You can read more about Truth Value testing here.
This expression doesn't do what you want:
choice == 'n' or 'N'
It is interpretted as this:
(choice == 'n') or 'N'
You might want to try this instead:
choice in 'nN'

If inside while loop

again = True
while(again == True):
yn = input("Do you want to do it again? (y or n)").lower()
if(yn == 'y' or 'yes'):
again == True
elif(yn == 'n' or 'no):
again == False
How do I make this code work? When I run it, it will always come out to be true.. =/
Let's start from the beginning:
while(again == True):
You don't need the parentheses here
You don't need the == True bit. again is suffice as it will have a boolean value of True.
if(yn == 'y' or 'yes'):
Once again, parenthesis aren't needed.
That line of code is translated as if (yn == 'y') or ('yes'):. This will always be true as 'yes' is considered True (not an empty string)
In python, you need to do if yn == 'y' or yn == 'yes':
Or you can do if yn in ('y', 'yes')
again == True
== is for comparisons. = is for assignments
This occurs in your else block.
In the final 4 lines of your program you aren't assigning again to have the value true, you are checking if again equals True/False.
== is completely different from =.
This won't work:
if (yn == 'y' or 'yes'):
# ...
elif(yn == 'n' or 'no):
The correct way is:
if yn in ('y' or 'yes'):
# ...
elif yn in ('n' or 'no):
Also, inside the conditions the assignments are wrong, use a single =. They should look like this:
again = True
# ...
again = False
You are mistaking the equality operator == with the assignment operator =. Also the statement yn == 'y' or 'yes' is buggy, since the right hand side is a non-empty string, which evaluates to True in a boolean context.
Declaring a variable simply to handle loop termination is not pythonic. I would rewrite your code entirely to be:
while True:
yn = input("Do you want to do it again? (y or n)").lower()
if yn in ('n','no'):
break
if(yn == 'y' or 'yes'):
# ----
The value of above statement is always true independent of valu of “yn” because right side of “or” is always true in your case. so it will never execute else part. So to avoid this, You have to compare value of “yn” with each possibility.
one of the simple way is that
if(yn == 'y' or yn == 'yes'):
again == True
elif(yn == 'n' or yn == 'no):
again == False
your if else statment should be
if xxx:
again = True
elif yyy:
again = False
Note difference between = and ==.

Categories