3

first we have this:

def some(a):
    if a is None or "*":
         print "*"
    else:
         print a

>>> some("*")
    *
>>> some("d")
    *

it failed but I couldn't give myself a good enough reason why it failed. Apparently it is because I wrote it wrong, a working version would be:

def some(a):
    if a in [None, "*"]: # or write [ if a is None or a is "*" ]
         print "*"
    else:
         print a


   >>> some("*")
       *
   >>> some("d")
       d

Although it's almost intuitive enough to just write the correct version but I couldn't explain to myself why the first version failed.

so the question is, why the first version failed?

stucash
  • 1,078
  • 1
  • 12
  • 23
  • 1
    Also note, the "working" version should be `a in [None, "*"]`. As you've written it, `(None or "*")` is evaluated as a boolean expression, which will return the first `True`-equivalent component, which is `"*"`. Then your code will test `a is "*"`. Try `some(None)` to see what I mean. – Matthias Fripp Nov 16 '17 at 23:25
  • @MatthiasFripp thanks for the note, I did miss that part, it should be in a square bracket. – stucash Nov 16 '17 at 23:28

3 Answers3

3

The statement:

if a is None or "*":

Semantically means

if ((a is None) is True) or (the value "*" is True)

And the value "*", being a non empty string is always True. Thus, the whole expression will evaluate to True.

donkopotamus
  • 22,114
  • 2
  • 48
  • 60
1

This will always evaluate as True

 if a is None or "*":

You could have said this if you wanted

 if a is None or a== "*":
SuperStew
  • 2,857
  • 2
  • 15
  • 27
1

The following statement doesn't do what you're expecting:

if a is None or "*":

This is equivalent to:

if (a is None) or "*":

so it's always True. To get the behavior you want, use:

if a is None or a == "*":
Tom Karzes
  • 22,815
  • 2
  • 22
  • 41