Python Forum

Full Version: Potential confusion combining != with or
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I'm trying to write a program for multiplication facts. It generates the list of facts, randomizes it, and then goes through. I just enter y or n depending on whether the student gets it right or wrong.

I'm having problems with this part:

for r in range(origlistsize): #this will be done origlistsize times (total # of problems in list)
    print(" Problem",r+1,"of",origlistsize,":",rndmultfacts[r])
    print()
    print()
    answer = input(" Is answer right (y) or wrong (n)? ")
    while answer.lower() != ("y" or "n"):
        answer = input(" Is answer right (y) or wrong (n)? ")
        print(" top r =",r) #debug
    if answer.lower()=="y":
        print("middle r =",r) #debug
        continue
    else:
        print("bottom r =",r) #debug
        errlist1.append(rndmultfacts[r])
        continue
Here's some output:

 Problem 1 of 16 : 3*2 = 6


 Is answer right (y) or wrong (n)? h
 Is answer right (y) or wrong (n)? h
 top r = 0
 Is answer right (y) or wrong (n)? h
 top r = 0
 Is answer right (y) or wrong (n)? h
 top r = 0
 Is answer right (y) or wrong (n)? h
 top r = 0
 Is answer right (y) or wrong (n)? h
 top r = 0
 Is answer right (y) or wrong (n)? h
 top r = 0
 Is answer right (y) or wrong (n)? y
 top r = 0
middle r = 0
 Problem 2 of 16 : 2*3 = 6


 Is answer right (y) or wrong (n)? y
middle r = 1
 Problem 3 of 16 : 0*0 = 0


 Is answer right (y) or wrong (n)? y
middle r = 2
 Problem 4 of 16 : 2*1 = 2


 Is answer right (y) or wrong (n)? y
middle r = 3
 Problem 5 of 16 : 3*1 = 3


 Is answer right (y) or wrong (n)? y
middle r = 4
 Problem 6 of 16 : 1*1 = 1


 Is answer right (y) or wrong (n)? y
middle r = 5
 Problem 7 of 16 : 0*2 = 0


 Is answer right (y) or wrong (n)? n
 Is answer right (y) or wrong (n)? n
 top r = 6
 Is answer right (y) or wrong (n)? n
 top r = 6
 Is answer right (y) or wrong (n)? n
 top r = 6
 Is answer right (y) or wrong (n)?
The y's and invalid entries seem to work, but the n's don't.

Is Line 6 of the code done correctly? My intent is to move past the while loop if either an "n" or "y" is passed. If the problem is correct ("y"), then, move onto the next problem. If incorrect then add to error list and move onto the next problem. Why is the latter not happening?
I would try to split it into two statements/evaluations (one on each side of "or"). I don't have Python open as I'm at work, so my syntax may be off.

 while answer.lower() != "y" or answer.lower() != "n":
(Oct-29-2019, 08:18 PM)Aurthor_King_of_the_Brittons Wrote: [ -> ]I would try to split it into two statements/evaluations (one on each side of "or"). I don't have Python open as I'm at work, so my syntax may be off.

 while answer.lower() != "y" or answer.lower() != "n":

That doesn't work: both "y" and "n" result in the program staying in the while loop.
while answer.lower() not in ("y", "n"):
or

while answer.lower() != "y" and answer.lower() != "n":
(Oct-29-2019, 08:02 PM)Mark17 Wrote: [ -> ]
answer.lower() != ("y" or "n"):

No-one has explained why this is wrong. In Python (and other languages too, actually), all values can be tested for being True or False (see the docs). Non-empty strings are treated as True, so the expression "y" or "n" evaluates to True. You then compare the return value of answer.lower() with True and the expression answer.lower() != True will always evaluate to True because answer.lower() returns a string and values of different types (string and bool here) will never be equal.
(Oct-31-2019, 06:37 AM)ndc85430 Wrote: [ -> ]You then compare the return value of answer.lower() with True and the expression answer.lower() != True will always evaluate to True because answer.lower() returns a string and values of different types (string and bool here) will never be equal.

Actually the second part of your explanation (the one I have quoted) is not correct. The first part about true-testing is correct.
"y" or "n" will return "y" (i.e. first element that is considered to be True). So if you have False or None or [] or 'spam' it will return 'spam'
And 'y' and 'n' will return 'n' - i.e. the last element considered to be True

That is why answer.lower() != ("y" or "n"): is same as answer.lower() != "y":
buran explanation backed-up with Python docs (already referenced earlier):

Quote:Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)

This behaviour enables writing 'clever' code like:

>>> lst = [1, 2, 3]
>>> for i in lst:
...     print(i % 2 and 'odd' or 'even')
... 
odd
even
odd
(Oct-29-2019, 09:14 PM)buran Wrote: [ -> ]
while answer.lower() not in ("y", "n"):
or

while answer.lower() != "y" and answer.lower() != "n":

Do I need to go back and retake Philosophy 101 (Intro to Logic)? :)
(Oct-31-2019, 12:10 PM)Mark17 Wrote: [ -> ]Do I need to go back and retake Philosophy 101 (Intro to Logic)?
not sure I understand your question
I was just being a bit self-deprecating.
Pages: 1 2