Reputation: 67
I'm working through 'Learn Python the Hard Way' and I've hit a roadblock. The book gives a unit test and asks you to write a function to satisfy the tests. But when I import this function to the interactive shell to test it out, any input returns 'direction' and I can't figure out why.
Here's my code:
def pos(item):
""" Get part of speech for item. """
pos = ''
if item == 'north' or 'south' or 'east':
return 'direction'
elif item == 'go' or 'kill' or 'eat':
return 'verb'
elif item == 'the' or 'in' or 'of':
return 'stop'
elif item == 'bear' or 'princess':
return 'noun'
else:
try:
int(item)
return 'number'
except ValueError:
return 'error'
Upvotes: 2
Views: 1991
Reputation: 123782
You're using or
wrong. It should be
if item == 'north' or item == 'south' or item == 'east':
or, more idiomatically,
if item in ('north', 'south', 'east')
The reason this is coming up wrong is because of the way Python puts the brackets in the expression. You might think it's doing
if item == ('north' or 'south' or 'east')
but what's actually happening is
if (item == 'north') or ('south') or ('east')
and 'south'
, being a non-empty string, is always True
. (Although, the former wouldn't work either, because 'north' or 'south' or 'east'
will be evaluated to 'east'
due to the way Python short-circuits or
. But that's more complicated and you don't need to worry about it.)
Incidentally, you may prefer the following idiom, though yours is just as good.
items = {}
items['north'] = items['south'] = items['east'] = 'direction'
items['go'] = items['kill'] = items['eat'] = 'verb'
items['the'] = items['in'] = items['of'] = 'stop'
items['bear'] = items['princess'] = 'noun'
try:
return items[item]
except KeyError:
pass
try:
int(item)
except ValueError:
pass
else:
return 'number'
return 'error'
Upvotes: 4
Reputation: 288280
if item == 'north' or 'south' or 'east':
determines the truth value of everything between or's. non-empty strings have the True truthvalue, so given the input 'west'
, this evaluate to:
if False or True or True:
Instead, you want
if item == 'north' or item == 'south' or item == 'east':
, or, more pythonic:
if item in ('north', 'south', 'east'):
Upvotes: 1
Reputation: 48101
You should have written this:
if item == 'north' or item == 'south' or item == 'east':
or, alternatively:
if item in ('north', 'south', 'east'):
The same applies for the remaining branches.
To explain why your original code failed, consider how Python parses the following expression:
item == 'north' or 'south' or 'east'
What Python does is as follows (note the parentheses which denote the order of parsing):
(item == 'north') or 'south' or 'east'
You have three sub-expressions here. item == 'north'
is likely to be false (unless you happened to have entered 'north'
). However, 'south'
or 'east'
, when evaluated in a boolean context (i.e. a condition), is always True
, so you end up with (item == 'north') or True or True
, which is of course True
.
Upvotes: 8