Jump to content

unexpected python if behaviour

doonm's Photo
Posted Jan 03 2011 07:27 PM
3722 Views

Is the following correct or is it a misunderstanding about the interpretation of the arguments?
How does one 'read' this expression?

>>> b = ['a','b','c']
>>> if ('z' or 'a') in b:
... print True
...
>>> if ('a' or 'z') in b:
... print True
...
True

Tags:
1 Subscribe


4 Replies

+ 1
  paulbarry's Photo
Posted Jan 04 2011 03:12 AM

You need to break down your code - bit by bit - to see what's going on, and your use of parens is changing the meaning of this code.

When Python see parens, it evaluates that code first, so:

('z' or 'a')


returns 'z', which isn't in b, so your expression is false. Note: 'or' short-circuits.

If you remove the parens:

if 'z' or 'a' in b:


things should work the way you expect, or use the parens like this:

if ('z' in b ) or ('a' in b ):


to do the same thing.

Main message: parens are *not* required around conditional expressions in Python in the same way that they are in other languages, and using them changes how things work.

Hope this helps.

Regards.

--Paul.
--
Paul Barry.
 : Jan 04 2011 01:01 PM
Thanks, that answers the question :)
>>> print ('z' or 'a')
z
>>> print ('a' or 'z')
a
>>>

Now I know why...
0
  doonm's Photo
Posted Feb 16 2011 04:53 PM

Another strange related thing..seems like the parenthesis thing was only part of the problem.

>>> fmt.keys()
['0', '3', '2', 'description']
>>> if 'date' or 'description' in fmt.keys():
... print fmt
...
{'0': 0, '3': 3, '2': 2, 'description': 1}
>>> if 'description' or 'date' in fmt.keys():
... print fmt
...
{'0': 0, '3': 3, '2': 2, 'description': 1}
>>> if 'description' and 'date' in fmt.keys():
... print fmt
...
>>> if 'date' and 'description' in fmt.keys():
... print fmt
...
{'0': 0, '3': 3, '2': 2, 'description': 1}
>>>

Yeah - the solution is to explicitly state each test - but a shortcut would have been nice... (Python 2.5.2 BTW)
+ 1
  mhalverson's Photo
Posted Feb 18 2011 02:03 PM

I think you are failing to understand the meaning of your tests.

What

if 'date' or 'description' in fmt.keys()

means is if 'date' is True, or if ('description' in fmt.keys()) is true, then do what is specified. As a string literal will always test true, your first two tests are true (True or True, True or False). Your third test is false (True and False) and fourth is true (True and True).

I'm not sure how to solve it other than to explicitly state each tests. With the set type in python 2.6 and above, it could be solveable by using set interections:

if set(['date','description']).intersection(fmt):
#at least one in fmt.keys()
print fmt

if set(['date','description']).issubset(fmt):
#all are in fmt.keys()
print fmt