1

I'm trying to learn why the following does not work:

I have a dictionary;

ex = {'CA':'San Francisco', 'NV':'Las Vegas'}

I tried to use if else statement to get 'yes':

>>> if ex['CA'] is 'San Francisco':
...     print 'yes'
... else:
...     print 'no'
... 
no

>>> 
>>> 
>>> if ex['CA'] == 'San Francisco' is True:
...     print 'yes'
... else:
...     print 'no'
... 
no

>>> if ex['CA'] == 'San Francisco' is True:
...     print 'yes'
... 
>>> 

Here, I don't get 'yes'

I want to understand why I'm not getting 'yes'

>>> ex['CA'] == 'San Francisco'
True

>>> ex['CA']
'San Francisco'

What would be the other ways if I want to use a conditional statement of key of dictionary equals to some value?

halo09876
  • 2,725
  • 12
  • 51
  • 71

1 Answers1

3

you're comparing ex['CA'] to 'San Francisco' (which is OK) and after that you're comparing 'San Francisco' to True which always fails: the result is always false (edited for correctness: the root cause was described wrong, but the fix is the same)

So the code is not doing what you think it's doing.

That'll work:

if (ex['CA'] == 'San Francisco') is True:

but the pythonic way remains:

if ex['CA'] == 'San Francisco':

is True is valid but I'd reserve it to a very particular usage, when you want to differentiate a non-zero value like 12 (or even 1) from True

other usages make it redundant.

BTW, I can't let you write if ex['CA'] is 'San Francisco': and get away with it. You have to use ==. True is a singleton so is works, but that's not guaranteed for strings, it's implementation dependent. See Python string interning for more details.

Community
  • 1
  • 1
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 4
    Side-note: Using `is True` *can* make valid code wrong, it's not *technically* equivalent to simple truthiness testing even for the result of `==` `is True`. `__eq__` is allowed to return any old object, not just `True`/`False`, so if parenthesized as `(ex['CA'] == 'San Francisco') is True` and `ex['CA']` is some custom object with a non-standard `__eq__` that returns, say, `1` on equal, and `0` on not equal, the identity comparison to `True` will always end up being false (1 is equal to `True`, but they're not the same object; if `__eq__` returned `2`, it wouldn't even be equal to `True`). – ShadowRanger Feb 25 '17 at 08:53
  • The problem has nothing to do with operator precedence, it's just how chaining comparison operators works. Basically, `ex['CA'] == 'San Francisco' is True` is equivalent to `ex['CA'] == 'San Francisco' and 'San Francisco' is True`, just like `a < b < c` is equivalent to `a < b and b < c` – stranac Feb 25 '17 at 11:12
  • I knew it was fishy when I wrote that. You're right. I'll fix this, it's wrong... funny thing I thought of `a < b < c` but didn't think of it applying here. – Jean-François Fabre Feb 25 '17 at 11:22