Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Basics All Together Now Branch and Loop

My IF statement always returns true with using OR.

Hi! I'm trying to use OR in my IF statement to try to make it more user friendly. For some reason it always comes back true, no matter what I write. What I mean is that my IF statement always runs no matter what I write with this code. Whats the problem?

This is the code I'm trying.

proceed = input("{}, would you like to proceed in this purchase?\nY/N ".format(user_name))

if proceed.lower() == "y" or "yes": print("Thank you for your purchase {}".format(user_name)) tickets_remaining -= how_many_tickets

else: print("Thanks {}, have a nice day!".format(user_name))

4 Answers

Jonathan Grieve
MOD
Jonathan Grieve
Treehouse Moderator 91,253 Points

I don't think there's a lot materially wrong with the code.

Maybe try making sure your indentations are correctly aligned. That is to say 4 spaces every time indentation is required. Python can be strict about it and can cause disruption to program flow.

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

One of the things I love about programming is that there many correct ways to write a program. Python is very forgiving in the way you can construct expressions, but there are always hidden "gotchas" along the way.

Let's evaluate what comes back from your if expression. You will note your expression will always result in 'yes' rather than the expected 'True' or 'False' which is what you intended.

>>> proceed='Yes'
>>> proceed.lower()=="y" or "yes"
'yes'
>>> proceed='No'
>>> proceed.lower()=="y" or "yes"
'yes'

To fix that, you can separate the expression logical tests.

>>> proceed='Yes'
>>> proceed.lower()=='y' or proceed.lower()=='yes'
>>> True
>>> proceed='No'
>>> proceed.lower()=='y' or proceed.lower()=='yes'
>>> False

Even better yet, which matches your intention to test the proceed response against several strings.

You could use a list of responses and the in operation.

>>> proceed='Yes'
>>> proceed.lower() in ['y','yes']
True
>>> proceed='NO'
>>> proceed.lower() in ['y','yes']
False

The resulting code is this.

proceed = input("{}, would you like to proceed in this purchase?\nY/N ".format(user_name))

if proceed.lower() in ["y", "yes"]:
    print("Thank you for your purchase {}".format(user_name))
    tickets_remaining -= how_many_tickets

else:
    print("Thanks {}, have a nice day!".format(user_name))

Great answer Jeff Munday! Thank you! I understand now why the IF expression did what it did, and how to fix it. But there is 2 things I still don't understand that you might be able to explain to me.

Why did it return 'Yes' instead of True or False?

And why did the IF expression run on a 'Yes'? Is that equal to a True?

Sorry that I might seem confused but still a very novice at this ;).

Thanks again for the answers everyone!

Jeff Muday
MOD
Jeff Muday
Treehouse Moderator 28,720 Points

Q: Why did it return 'Yes' instead of True or False?

Great question to ask! I totally encourage you to do experiments with the Python REPL when you are in doubt about how operations work.

The overarching reason we see these strings returned as values comes from the design concept "operator overloading" and "operator short-circuit". Python (mostly but not always) allows mixing of types and operators (operator overloading). This includes Boolean operators. The idea of "short-circuit" is that the Python interpreter will evaluate the order of operations of a logical equation and it won't go on to evaluate anything else unless it needs to (this saves time). For example "or" short-circuits when the LEFT side evaluates to True. And "and" short-circuits if the LEFT side evaluates to False.

The other oddity of Python is something Kenneth calls "truthiness". Any non-zero number is considered "truthy" or True. Any string that has one or more characters in it is called "truthy" or basically equivalent to True. An integer 0, empty string, or None value are considered to be "falsey" or False in terms of logical flow.

Python will let you get away with using strings and numbers with logical operators e.g. and, or, not -- these are syntactically correct and there are some programming tricks you can do with these, though I don't necessarily recommend. I will demonstrate below.

Consider the following.

>>> # the "or" operator short-circuits since LEFT side is truthy
>>> # since "yes" is truthy, return the LEFT string!
>>> "yes" or "no"
'yes'
>>> # note that this works with 'no' too.
>>> "no" or "yes"
'no'
>>> True or "I am Truthy too, but short-circuit gives LEFT expression"
True
>>> # since there is not a short-circuit, return RIGHT truthy expression
>>> False or "I can say I am False, but I am truthy"
'I can say I am False, but I am truthy'
>>> # the "and" operator doesn't short circuit because
>>> # the LEFT side is truthy, so it evaluates the RIGHT
>>> # and this is also truthy, so returns the truthy string.
>>> "yes" and "no"
'no'
>>> # this also returns the RIGHT truthy expression
>>> "no" and "yes"
'yes'
>>> # the "not" operator short-circuits since "yes" is truthy
>>> # and returns False
>>> not "yes"
False
>>> # "no" is truthy so will also return False
>>> not "no"
False
>>> # note the "falsey" empty string and None
>>> # will return True
>>> not ""
True
>>> not None
True
>>> not 0
True

I hope this helps!