Home > Mobile >  Why does this function not return the correct conditional result?
Why does this function not return the correct conditional result?

Time:06-22

Functions have always been my weakness. I'm trying to write a simple conditional within a function to test my function skills. (I know that it doesn't need to be in a function but I'm exploring).

However, I cannot work out why this function is not returning the correct conditional output?

When I enter anything other than '42' or 'forty-two' or 'forty two' it still responds with "Yes".

def meaning_of_life():
    meaning = ponder(input("What is the Answer to the Great Question of Life, the Universe, and Everything? "))
    print(ponder(meaning))

def ponder(meaning):
    if meaning == "42":
        return "Yes"
    elif meaning == "forty-two" or "forty two":
        return "Yes"
    else:
        return "No"


meaning_of_life()

CodePudding user response:

Change this:

elif meaning == "forty-two" or "forty two":

to this:

elif meaning == "forty-two" or meaning == "forty two":

CodePudding user response:

Issue: or True

The evaluation of your elif condition is as follows:

  1. meaning == "forty-two" is False for any non-match
  2. the next part after or is True because a non-empty string like "forty two" is True (we call it truthy)

The order of evaluation is controlled by operator precedence.

In that case the conditional evaluates to False or True which is finally always True. Even with other cases as non-match the last or True will guarantee that the elif branch if reached will always be True.

Test boolean evaluation of conditions

You can test it in Python REPL:

>>> meaning = 'nothing'
>>> meaning == "forty-two" or "forty two"
'forty two'
>>> bool(meaning == "forty-two" or "forty two")
True

Or when using your script, add debug-prints:

print(meaning == "forty-two" or "forty two")
print(bool(meaning == "forty-two" or "forty two"))

Fix the boolean logic

to have each equals condition separate:

elif meaning == "forty-two" or meaning == "forty two"

See also: How to test multiple variables for equality against a single value?

Simplification

The conditional (if-statement) to test for multiple cases can be simplified using the in operator against a tuple, set or list:

    if meaning in ("42", "forty-two", "forty two"):
        return "Yes"
    else:
        return "No"

or as pattern to map a value even shorter:

return "Yes" if meaning in ("42", "forty-two", "forty two") else "No"

Try it in the REPL:

>>> meaning = 'nothing'
>>> "Yes" if meaning in ("42", "forty-two", "forty two") else "No"
'No'

and test a negative-case (string '42') plus the edge-case (number 42 as int):

>>> meaning = "42"
>>> "Yes" if meaning in ("42", "forty-two", "forty two") else "No"
'Yes'
>>> meaning = 42
>>> "Yes" if meaning in ("42", "forty-two", "forty two") else "No"
'No'

Still issues with meaning_of_life()?

Explained a potential logical bug with my comments:

def meaning_of_life():
    meaning = ponder(input("What is the Answer to the Great Question of Life, the Universe, and Everything? "))
    # Warning:  meaning was already pondered upon! So meaning is either 'Yes' or 'No' 
    # Still want to ponder again on `Yes` or `No` ?
    print(ponder(meaning))  # ponder on the pondered meaning and print the result 

def ponder(meaning):
    # print(type(meaning))
    return 'Yes' if str(meaning) in ('42', 'forty-two', 'forty two') else 'No'

meaning_of_life()

See the two invocations of ponder:

meaning = ponder( .. )
.. ponder(meaning) ..

Is same as ponder(ponder( .. ))) (we call this recursion)

Fix meaning_of_life()

To:

def meaning_of_life():
    answer = input("What is the Answer to the Great Question of Life, the Universe, and Everything? ")
    print(ponder(answer))  # ponder on the answer and print the result 
  • Related