0
def max_num(num1, num2, num3): return max(num1, num2, num3) if num1 == num2 or num1 == num3 or num2 == num3: return "It's a tie" 

This code isn't returning "It's a tie" when it should be. Might be a simple error as new to coding but struggling to understand. Thanks!

1
  • 3
    Consider tracing through your code one step at a time. Is there something you encounter before the if statement that might preclude it from running? Commented Aug 29, 2022 at 17:09

3 Answers 3

1

This code is never reaching the conditional statement because the return statement will always exit the function. Instead write:

def max_num(num1, num2, num3): m = max(num1, num2, num3) if num1 == num2 or num1 == num3 or num2 == num3: return "It's a tie" else: return m 

This will return "It's a tie" if any two of the numbers are the same, otherwise the largest of the three.

Alternatively this is a more efficient way of writing it:

def max_num(num1, num2, num3): if num1 == num2 or num1 == num3 or num2 == num3: return "It's a tie" else: return max(num1, num2, num3) 

This means the maximum is only calculated if there is no tie so the function is more efficient.

Sign up to request clarification or add additional context in comments.

Comments

0

You (roughly) wrote:

return a_value if condition: return different_value return None 

Please understand that the initial return prevents the rest of the code from running. We call it "unreachable code". The flow of control transfers when we hit the return, so subsequent statements are never even considered for evaluation.

Also, falling off the end of a Python function (the else clause of your if) will default to returning a None object.

You want to first evaluate the if, and then return the numeric maximum value.


Python is a dynamically typed language, so it is kind of OK to have mixed return types, such as str / int as we see here.

But it's not a best practice. It tends to make it hard for the calling function to consume the return value. For example, the expression

1 + max_num(a, b, c) 

will evaluate nicely on some of your tests, but it will raise an error on e.g. 1 + max_num(2, 2, 3). This example also highlights a code defect in the OP logic.

Note it is quite different from 1 + max_num(2, 3, 3), where there truly is a legitimate tie for maximum.

When designing a public API, consider how the consumer will use the return value. In this case, you might want to return a tuple:

m = max(num1, num2, num3) is_tie = ( (num1 == num2 == m) or (num1 == num3 == m) or (num2 == num3 == m)) return m, is_tie 

OTOH if consumer will merely print it, then the current API is just fine.

1 Comment

An approach to handling the "It's a tie" scenario might be to raise an exception. The caller can assume the return value of max_num is int and choose how it wants to handle the TieException.
0

At the first return the function exits. Control flow never reaches the conditional. Perhaps you meant the following, checking for a tie, otherwise returning the maximum number.

def max_num(num1, num2, num3): if num1 == num2 or num1 == num3 or num2 == num3: return "It's a tie" else: return max(num1, num2, num3) 

As a sidenote, another way to check for a tie would be to check the length of a set created from the three numbers. A set will not contain duplicates, so if it's less than 3, there must be a tie.

def max_num(num1, num2, num3): if len(set([num1, num2, num3])) != 3: return "It's a tie" else: return max(num1, num2, num3) 

Rather than returning a string from your function in the event of a tie, you may wish to raise an exception so the calling code can handle that situation as it sees fit.

class TieException(Exception): pass def max_num(num1, num2, num3): if len(set([num1, num2, num3])) != 3: raise TieException return max(num1, num2, num3) try: print(max_num(1, 2, 2)) except TieException: print("It's a tie") 

Note that else is not necessary here because raising the exception also forces control flow to leave the function. The return will not be evaluated if the fist condition is true.


You might also use count to check for a tie situation.

def max_nums(num1, num2, num3): nums = [num1, num2, num3] if any(nums.count(n) > 1 for n in nums): raise TieException return max(nums) 

This has the benefit of scaling so that any number of numbers can be passed in. Though you may wish to raise a TypeError exception if no numbers are provided.

def max_nums(*nums): if len(nums) == 0: raise TypeError("max_nums requires at least one argument") if any(nums.count(n) > 1 for n in nums): raise TieException return max(nums) 

Of course, we also don't need to know the count. This would be very inefficient for a large list. Instead we just need to check if any number is in the rest of the list after it. This will stop as soon as it finds a duplicate, indicating a "tie."

def max_nums(*nums): if len(nums) == 0: raise TypeError("max_nums requires at least one argument") if any(x in nums[i+1:] for i, x in enumerate(nums)): raise TieException return max(nums) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.