Python: Keyboard prompt with capital/noncapital letters - python

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!")

Related

Why is there error with " != " not equal in my code while comparing strings in python?

I got error while comparing the strings. What is the error here?
I was unable to find the problem and its solution.
My code is this:
def login():
user_name=input("Enter the user name:")
password=input("Enter the password:")
confirm=input("Confirm the above information is correct (y/n):")
if confirm != 'y' or confirm != 'Y':
print("Is not true!")
login()
return user_name,password
I am getting this instead of returning the values?
Enter the user name:>? vsdfv
Enter the password:>? cvsdf
Confirm the above information is correct (y/n):>? y
y
Is not true!
Enter the user name:
Because you are using or, one of the conditions will always be true. Use and instead
if confirm != 'y' and confirm != 'Y':
print("Is not true!")
or in basically every programming language is not the same as "or" in natural language. In computer science it means that the overall expression is true, if at least one of both sub-expressions evaluates to true. Therefore, your boolean expression always yields true, because if the first expression evaluates to true, the second will evaluate to false and the other way around.
You used or and you entered y. Since one of the conditions is true
(confirm != 'Y'), it will evaluate to true.
Use and instead.

Python will not accept user inputs [duplicate]

This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
Closed 7 years ago.
I managed to get this code to work before, but I've changed something accidentally and can't figure out what.
The code that will not work is:
while True:
answer = input ("Would you like to play this game? Type yes if you would like to. Type no to end the program")
if answer == 'no' or 'n' or 'No' or 'N':
sys.exit()
elif answer == 'yes' or 'y' or 'Yes' or 'Y':
code = input("Input a three digit code. Must be more than 001 and less than 100.")
When I run the code and put in one of the answers, the program will not run the next part and gives no error message.
In case it is necessary, I have put the code for the entire program below:
import random
import sys
while True:
answer = input ("Would you like to play this game? Type yes if you would like to. Type no to end the program")
if answer == 'no' or 'n' or 'No' or 'N':
sys.exit()
elif answer == 'yes' or 'y' or 'Yes' or 'Y':
code = input("Input a three digit code. Must be more than 001 and less than 100.")
try:
value = int(code)
except:
print ("Invalid code")
continue
if 1 <= value <= 100:
print (code)
print ("Valid code")
print ("I will now try to guess your number")
number = random.randint(1, 100)
while number > int(code) or number < int(code):
print ("Failed attempt. Number guessed is")
number = random.randint(1, 100)
print (number)
else:
if number == int(code):
print ("Your code is")
print (code)
else:
print ("Invalid code")
EDIT: Thank you so much, the yes option is working now, but the program will still not exit when selecting any of the no options, as it did before. The edited code is:
if answer in ('no', 'n', 'No', 'N'):
sys.exit()
elif answer in ('yes', 'y', 'Yes', 'Y'):
I checked by printing the answer value, and i believe it is registering the no input but not executing the command that follows for some reason.
EDIT: I'm still a bit fuzzy on the logic, but changing it to exit() fixed the problem. It asks for confirmation when closing now, when it didn't before, but otherwise sorted.
Problem causing silent exit:
if answer == 'no' or 'n' or 'No' or 'N':
sys.exit()
That test is testing answer == 'no' as one test, then 'n' as a separate test, and so on. or chains return when any test returns a "truthy" value (or the last evaluated value if none are truthy), so the test always ends up evaluating as "truthy" because a non-empty string like 'n' is truthy. If you're trying to test for any one of those values, you'd do an "is contained in" test to see if answer is one of a recognized group of values, e.g.:
if answer in ('no', 'n', 'No', 'N'):
The reason is due to this expression:
if answer == 'no' or 'n' or 'No' or 'N':
In python, the above is exactly the same as this:
if (answer == 'no') or ('n' != '') or ('No' != '') or ('N' != ''):
Since all but the first expression evaluates to true, the whole expression is true.
The simplest solution is to convert your input to lowercase and trim off any extra space, then check if the answer is in a list of allowable answers so that you can easily compare for "n", "N", "no", "NO", "No", "nO".
if answer.strip().lower() in ("n", "no"):

Python loop keeps repeating? Why?

Another_Mark = raw_input("would you like to enter another mark? (y/n)")
while Another_Mark.lower() != "n" or Another_Mark.lower() != "y":
Another_Mark = raw_input("Do you want to input another mark? Please put either 'y' or 'n' this time")
if Another_Mark == "y":
print "blah"
if Another_Mark == "n":
print "Blue"
This is not the actual code I'm using except for the 1st three lines. anyways my question is why does the while loop keep repeating even when I input a value 'y' or 'n', when it asks again if you want to input another mark on the third line. I'm stuck in a infinitely repeating loop.
It shouldn't repeat when the value for Another_Mark is changed to either "y" or "n"
Try:
while Another_Mark.lower() not in 'yn':
Another_Mark = raw_input("Do you want to input another mark? Please put either 'y' or 'n' this time")
not in operator returns true if given object is not found in the given iterable and false otherwise. So this is the solution you're looking for :)
This wasn't working due to boolean algebra error fundamentaly. As Lattyware wrote:
not (a or b) (what you describe) is not the same as not a or not b
(what your code says)
>>> for a, b in itertools.product([True, False], repeat=2):
... print(a, b, not (a or b), not a or not b, sep="\t")
...
True True False False
True False False True
False True False True
False False True True
Your loop logic only every comes out true - if the input is "n", then it's not "y" so it's true. Conversely if it's "y" it's not "n".
Try this:
while not (Another_Mark.lower() == "n" or Another_Mark.lower() == "y"):
Another_Mark = raw_input("Do you want to input another mark? Please put either 'y' or 'n' this time")
Your logic behind the looping is wrong. This should work:
while Another_Mark.lower() != "n" and Another_Mark.lower() != "y":
Another_Mark = raw_input("Do you want to input another mark? Please put either 'y' or 'n' this time")
You need to use AND instead of OR.
It's the way boolean logic distributes. You can say:
NOT ("yes" OR "no")
Or you can distribute the NOT into the parenthesis (which is what you're trying to do) by flipping the OR to an AND:
(NOT "yes") AND (NOT "no")

Why does my elif go back to my if?

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,

OR behaviour in python:

I have written the following piece of code, all i want to do is print a yes for if the number passed is a string representation of 1, 0 or 2 and for everything else a false:
number=raw_input()
if number is "1" or "0" or "2":
print "Yes"
else:
print "no"
I know how to make the intended logic work, but i just want need to know why it prints yes for any number i pass to raw_input. I'd like the answer to be as detailed as possible, because i cant understand why it would fail, it seems pythonic enough to me
The problem is that your code, to Python, reads like this:
if (number is "1") or "0" or "2":
And as any non-empty string evaluates to True, it's always True.
To do what you want to do, a nice syntax is:
if number in {"1", "0", "2"}:
Note my use of a set here - while it doesn't matter too much in this case (with only three values) checking against a set is faster than a list, as a membership test for a set is O(1) instead of O(n).
This is simply a nicer and easier of writing this:
if number == "1" or number == "0" or number == "2":
Which is what you wanted.
Note when making a comparison for value you should always use == not is - is is an identity check (the two values are the same object). Generally you should use is for stuff like is True or is None.
If you wanted to handle this as a number, you could do something like this:
try:
value = int(number)
except ValueError:
value = None
if value is not None and 0 <= value <= 2:
...
Which could be more useful in situations where you want to compare to a large range of numbers. Note my use of Python's useful comparison chaining (0 <= value <= 2 rather than 0 <= value and value <= 2).
The correct syntax is as follows:
if number == "1" or number == "0" or number == "2":
print "Yes"
Or the more Pythonic:
if number in ["1", "2", "3"]:
print "Yes"
Or you can cast to int and try:
if int(number) in range(1,4):
print "Yes"
The reason your code evaluates to True is all the time is because it is evaluating the truth of the "0" and "2", which as statements are true in Python.
Because every expression between an or is evaluated as a boolean expression.
if True evaluates to True, if 1: evaluates to True, if "0": evaluates to True.
So what you wrote is more or less the equivalent to:
if number is "1":
print "Yes"
elif "0":
print "Yes"
elif "2":
print "Yes"
else:
print "no"
You should have written if number is "1" or number is "0" or number "2": or, more pythonic: if number in ("1", "0", "2"):

Categories