Time Complexity of Algorithms - TypeError while comparing

Screen Link: Learn data science with Python and R projects

My Code:

def maximum(values):
    answer = None
    for val in values:
        if answer < val or answer == None :
            answer = val
    return answer

What I expected to happen:
Get the max value from the list via comparison

What actually happened:

TypeError: '<' not supported between instances of 'NoneType' and 'int'

Am getting the above error with my code. If I just interchange the comparison condition in IF i.e. putting the None comparison first and then the less then, it gets executed successfully.

Can someone explain why is this happening? Am assuming order of comparison shouldn’t matter, right?

1 Like

Hi @vkarthik21,

Welcome to the Community!

The order here matters in terms that Python executes the code from left to right. And yes, you can’t compare a None to an integer value, otherwise it will throw an error. If instead you interchange the conditions in the if-statement starting from checking if the value is a None, you’ll avoid this issue.

1 Like

Thanks Elena for the update. It’s still bit confusing for me.

Approach 1 -

answer == None or answer < val

Approach 2 -

answer < val or answer == None

In both cases, we ARE comparing None to a Integer value. Shouldn’t it cause in error in both the cases consistently? Why is left to right reading of python cause such incorrect value?

I mean isn’t a condition like- var_1 < 5 or var_1 == 6 same as var_1 == 6 or var_1 < 5 both mean the same?

1 Like

@vkarthik21: Think of it as a “catch”. When we initialize the answer to None to keep track of the maximum value, in the first iteration of the loop, answer will definitely be None. Nonetype and int comparisons aren’t allowed in python (None compared to val which is an integer). On the subsequent iterations, answer will get updated, so answer will be of type int (assuming we are using the list provided to check the function: [4, 3, 5, 6, 2, 1]. So this order is predominantly to serve as a catch (for the first iteration).

We can of course not initialise answer to be None, which would rid the problem (and instead 0). Not sure if this was intentional but I agree it is slightly confusing.

In that case you honestly don’t need the None check.

def maximum(values):
    pass
def maximum(values):
    answer = 0
    for val in values:
        if answer < val:
            answer = val
    return answer

max_value = maximum(test_values)

Kindly raise a ticket about this to the content team. I also would like to know if this was intentional lol. I raised a ticket myself. Let’s see what they say when they get back…

Order matters, once a statement is evaluated to true, the second won’t be evaluated since we are using the or logical operator here. If we just do a direct comparison with the None and int, there will be an error (and the comparison of answer of value None with None will not take place), whereas if we check answer to be None in the first case, it will evaluate to true and the subsequent checks will be voided.

1 Like

Its slightly convoluted in that sense lol :sweat_smile: also took a while to understand haha… You can use the alternative method it should work.

Thank you so much @masterryan.prof detailed explanation. It makes perfect sense now. Yes, it’s definitely akin to catch.

Appreciate you raising a ticket and I can see how this has been so quickly picked up.

Coming to initializing with 0, wouldn’t that cause a problem if there are only negative values in the list?

1 Like

@vkarthik21: there should be no issues… (unless you have None in the list itself). Usually I initialise stuff with zeros (esp. when I am going to do some sort of integer operations )

test_values = [-10, 4, 3, 5, 6, 2, 1, -20]

def maximum(values):
    pass
def maximum(values):
    answer = 0
    for val in values:
        if answer < val:
            answer = val
    return answer

max_value = maximum(test_values)

image

Ya I’m also not sure why they used the None check, might not be scalable (e.g. if you have None in the middle nearer to the end of the list for their solution). Depends on the context I would say… Their answer worked for these set of lists coz of positive integers but might not be so scalable throughout… So depends on your data set ultimately… shows you how important EDA is (coz you might have to tweak your code based on your data itself to accommodate negative integers, Nonetypes etc.). If my answer helped you do you mind marking it as a solution so that others can quickly identify what they needa know in future? Thanks!

1 Like

Thanks again @masterryan.prof . If we pass a list with only negative integers and initialize the answer with 0, then the output returned would be 0 which is incorrect. I guess having None makes sense.

Yep. So it depends on the case based on your data input.