What's wrong with my if-else statements in Python 3?

In summary, the code will output: Tire rotation for any input that I enter for auto_serv. Where have I made a mistake? Any better ideas to program this?
  • #1
astroman707
61
5
Goal:
I'm trying to allow the user to input varying spellings for certain auto services, and still have my code work properly. My goal was to use the if-else statements to ensure that if the user misspelled a service, the code could correct the error by changing the variable assignment to the string that matched my dictionary key.
The issue:
The code will output: Tire rotation for any input that I enter for auto_serv. Where have I made a mistake? Any better ideas to program this? Keep in mind, I'm a first time programmer that's doing this for class, and I just learned if-else statements.
The code:
Python:
# dictionary assigns the cost for each service
services = {'Oil change': 35,
            'Tire rotation': 19,
            'Car wash': 7,
            'Car wax': 12}
# auto_serv is the user's desired car service
auto_serv = input('Desired auto service:')
# The following four 'if' statements are to allow the user multiple variances in spelling of desired auto service
if auto_serv == 'Tirerotation' or 'tirerotation':
    auto_serv = 'Tire rotation'

elif auto_serv == 'Oilchange' or 'oilchange':
    auto_serv = 'Oil change'

elif auto_serv == 'Carwash' or 'carwash':
    auto_serv = 'Car wash'

elif auto_serv == 'Carwax' or 'carwax':
    auto_serv = 'Car wax'

# the if-else statements are to give a result for each service the user requests
if auto_serv == 'Tire rotation':
    print('You entered:', auto_serv)
    print('Cost of %s: $%d' % (auto_serv, services[auto_serv]))

elif auto_serv == 'Oil change':
    print('You entered:', auto_serv)
    print('Cost of %s: $%d' % (auto_serv, services[auto_serv]))

# ...there are more elif statements that follow this code with the other auto services
 
Technology news on Phys.org
  • #2
One thing you can do is convert the input to either all lowercase or all uppercase, strip the input to remove spaces at the from or back and change your if expressions accordingly. Next you can drop the first if/elif group as they just map the input to an acceptable string.
 
  • #3
Your if/elif statements need to be changed to, for example:

if auto_serv == 'Tirerotation' or auto_serv == 'tirerotation':
 
  • Like
Likes Yelzobj, astroman707, Mark44 and 2 others
  • #4
tldr; wot she said ^

I'm not a Python programmer but, given the output and assuming no warnings popped up, it looks like your current code is telling the compiler to do a bit-logic operation on the two strings, which is way above your pay grade as a "first time programmer".

As far as "could it be better?" is concerned, sure, but - more importantly - does it incorporate everything you've learned up to this point in the course, plus what you could reasonably be expected to investigate on your own.
 
  • #5
To say what the others have said, but in different words,

if auto_serv == 'Tirerotation' or 'tirerotation':

Translates, depending on the language, to:

1) if (auto_serv == "Tirerotation') or (if "tirerotation' evaluates to a Boolean experssion which is true) then

2) if (auto_serv == "Tirerotation') evaluates to all 0's or all 1's and then LOGICALLY OR'ed with the binary values of 'tirerotation'

CLEARLY #2 is not even remotely what you want and #1 is just what happens when, as Sarah pointed out, you omit the conditional on the second part.
 
  • #6
The correction made by @Sarah Hrmbree is correct. The subsequent explanations for why your code does what it does are not, unless python 3 has completely changed handling of if and or since 2.7 (and I couldn't find any docs saying it has done). The or operator is not a bitwise operator in python; it's strictly a boolean comparison. The bitwise-or operator is | in python.

What is happening is that your line
Python:
if auto_serv == 'Tirerotation' or 'tirerotation':
means if auto_serv=='Tirerotation' is true, or if 'tirerotation' is true, then do whatever. The problem is what python does when you ask if a string is true. Any non-empty string is treated as true, and only an empty string is false. Since 'tirerotation' is not an empty string the condition is always true and the first branch always executes. All of the other elif conditions also evaluate to true for the same reason, but since the first branch executed the code doesn't consider any other.

There are many ways to improve this code. In terms of incremental improvements, I would look up python's in operator as well as considering converting to lower or upper case as @jedishrfu recommends.
 
  • Like
Likes m4r35n357 and jedishrfu
  • #7
...and one more thing, @astroman707. In your second if/elif tree, have you noticed how every branch is identical? Why are you bothering making a decision if you are going to do the same thing whatever the result of the decision?

And after you've fixed that you could look at whether you could use a similar approach to remove your first if/elif tree.
 
Last edited:
  • Like
Likes m4r35n357
  • #9
Sarah Hrmbree said:
Your if/elif statements need to be changed to, for example:

if auto_serv == 'Tirerotation' or auto_serv == 'tirerotation':
Thank you! That was the error staring me right in the face!
 
  • Like
Likes jedishrfu
  • #10
Thanks everyone for your inputs! Some of your suggestions are a bit too advanced for me, but still all interesting and helpful. Thanks!
 
  • Like
Likes jedishrfu
  • #11
[Moderator's note: off topic content deleted.]

The right approach is to use a jaccard index to match input similarity to the list of keywords you have in your services, and return the highest matching value.
 
Last edited by a moderator:
  • #12
Python:
def jaccard(a, b):
    union = list(set(a+b))
    intersection = list(set(a) - (set(a) - set(b)))
    return float(len(intersection))/len(union)

# dictionary assigns the cost for each service
services = {'Oil change': 35,
            'Tire rotation': 19,
            'Car wash': 7,
            'Car wax': 12}
user_input = input('Desired auto service:')
matching_service = sorted([(service, jaccard(user_input, service)) for service in services.keys()], key=lambda x:x[1], reverse=True)[0][0]
print("Best matching service:", matching_service, "and cost:", services.get(matching_service))
 
Last edited:
  • #13
[Moderator's note: Off topic content deleted.]

cronxeh said:
The right approach is to use a jaccard index to match input similarity to the list of keywords you have in your services, and return the highest matching value.
Based on the OP's statement that some of what was already said is above his current knowledge, your approach with lists and sets is probably waaaay beyond his level of expertise.
 
Last edited by a moderator:
  • #14
One of his requirements was to "still have my code work properly." With his current approach it would not scale as more services are added to the dictionary, or if it is refactored to pull from a database.

[Moderator's note: Off topic content deleted.]
 
Last edited by a moderator:
  • #15
Sarah Hrmbree said:
Your if/elif statements need to be changed to, for example:

if auto_serv == 'Tirerotation' or auto_serv == 'tirerotation':

A way to spell this that works better as more alternatives pile up is:

if auto_serv in ('Tirerotation', 'tirerotation'):
 
  • #16
astroman707 said:
I'm trying to allow the user to input varying spellings for certain auto services, and still have my code work properly. My goal was to use the if-else statements to ensure that if the user misspelled a service, the code could correct the error by changing the variable assignment to the string that matched my dictionary key.

Some good pointers have been given for how to do this better; but you might also consider the suggestion @jedishrfu made, which, in more general contexts, goes by the name of "canonicalization": instead of trying to explicitly list all the ways users might incorrectly capitalize or misspell words, apply a function to each user input that forces it into a standard form (such as all lower case, all upper case, Capitalized First Letters Of Each Word, or whatever), and then just test for the standard form. Python's string objects have a rich set of methods for doing this; the most general is probably the "translate" method.
 
  • #17
cronxeh said:
The right approach is to use a jaccard index to match input similarity to the list of keywords you have in your services, and return the highest matching value.

This approach is probably too much for the OP given his stated experience with Python. However, it's worth pointing out that if you do this, you will end up with a matching service even if the user types in word salad. So with this approach it's a good idea to confirm with the user that your code picked the correct matching service, before doing anything else with it.
 
  • #18
harborsparrow said:
I would ditch all those IF's and use a switch case statement instead

There is no switch case statement in Python; what your link is describing is how to implement functionality that mimics what that statement does in other languages.

Doing a dictionary lookup (including having functions as values in the dictionary) instead of multiple if/else clauses, which is what the link describes, is indeed a very useful technique in Python; I use it all the time. But it only helps with part of problem the OP is trying to solve, since it still requires an exact match in the dictionary, which means you would have to have an explicit entry for each possible misspelling of each service.
 
Last edited:
  • #19
Moderator's note: Off topic posts and content about switch statements has been deleted. Please keep discussion focused on the OP's specific problem.
 

FAQ: What's wrong with my if-else statements in Python 3?

How do I fix my if-else statements in Python 3?

To fix your if-else statements in Python 3, you should first check for syntax errors in your code. Make sure you have used the correct indentation and that you have closed all parentheses and brackets. You should also check your logic to ensure that your conditions are properly evaluating the correct values.

Why is my if-else statement not working in Python 3?

There could be several reasons why your if-else statement is not working in Python 3. Some common causes include incorrect indentation, missing or misplaced parentheses or brackets, or incorrect use of comparison operators. It is also possible that your code is not properly handling all possible cases, leading to unexpected behavior.

Can I use multiple conditions in an if-else statement in Python 3?

Yes, you can use multiple conditions in an if-else statement in Python 3. This can be achieved by using logical operators such as "and" and "or" to combine multiple conditions. It is important to carefully consider the placement of these operators to ensure that your conditions are properly evaluated.

How do I debug my if-else statements in Python 3?

To debug your if-else statements in Python 3, you can use print statements to check the values of your variables and conditions at different points in your code. This can help you identify where the issue is occurring. You can also use a debugger tool, such as the built-in debugger in most IDEs, to step through your code and track the flow of execution.

Are there any best practices for writing if-else statements in Python 3?

Yes, there are some best practices to keep in mind when writing if-else statements in Python 3. These include using consistent indentation, using descriptive variable names, and avoiding nested if-else statements when possible. It is also important to properly handle all possible cases and to test your code thoroughly to ensure it is functioning as expected.

Similar threads

Replies
18
Views
2K
Replies
11
Views
2K
Replies
3
Views
3K
Replies
4
Views
3K
Replies
75
Views
5K
Replies
2
Views
2K
Back
Top