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:
meaning == "forty-two"
isFalse
for any non-match- the next part after
or
isTrue
because a non-empty string like"forty two"
isTrue
(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