0

Hey guys so I've almost solved this kata but my code keeps failing this one test. Any ideas?

def move_zeros(array):
    n = len(array)
    count = 0
    
    for i in range(n):
        if array[i] is not 0:    
            if type(array[i]) != int or type(array[i]) != float:
                array[count] = array[i]
                count += 1
            else:
                array[count] = array[i]
                count += 1
            
    while count < n:
        array[count] = 0
        count += 1
    return array

This is the failed test:

[9, 0.0, 9, 1, 2, 1, 1, 0.0, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0] should equal [9, 9, 1, 2, 1, 1, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].

I assume its that float value throwing it off so I try and account for it with the second if statement, but to no avail.

Sanjay SS
  • 568
  • 4
  • 14

2 Answers2

1

Don't use the is not when comparing numbers. This is not the intended usage. Instead use the == comparison operator.

is and is not or used to compare actual objects, not literals.

Exelian
  • 5,749
  • 1
  • 30
  • 49
  • Hey thanks for the reply but the reason I used `is not` is because then another test fails if I use `!=`: `[1, None, 2, 1, 0, 0, 0] should equal [1, None, 2, False, 1, 0, 0]` is what fails along with the original one. When I use `is not` this test passes. – Marcelino Velasquez Jul 07 '20 at 20:50
1

Diving deeper into why this won't work because of use of is:

is checks that the objects literally refer to the same object. All numbers are objects in python but the int object for 0 is different from the float object for 0.0.

Under "the hood", these objects allow for equality between ints and floats by defining an appropriate __eq__ method which is ultimately what is used when you call 0 == 0.0.

Ryan Schaefer
  • 3,047
  • 1
  • 26
  • 46
  • Yes, but even two `int`s can/will be different objects even if they have the same value. try `a = 123456789`, `b = 123456789`, `a is b` on a standard python interpreter. – Kevin Wang Jul 07 '20 at 18:03
  • Ahh! Another fun fact, when you assign a number to a variable, it actually becomes its own separate object, so you are actually creating two different objects in that case. So `a` is an object with some memory address representing the number 123456789 whereas `b` is at another one. Therefore, `123456789 is 123456789` works whereas the example of assigning them to variables does not. – Ryan Schaefer Jul 07 '20 at 18:08
  • 1
    Apparently, that is only true for "sufficiently large" numbers like your example. I tried byte boundaries and it appears 1 byte works whereas 2 bytes does not and I don't know where in between that drops off. – Ryan Schaefer Jul 07 '20 at 18:15
  • yeah sorry I should have mentioned that. here's a good writeup on the range https://stackoverflow.com/questions/306313/is-operator-behaves-unexpectedly-with-integers and note that this is merely an implementation detail of the standard python interpreter and can be different in e.g. pypy so you should just not rely on `is` working for equality for `int`s. – Kevin Wang Jul 07 '20 at 18:44
  • Hey guys thanks for the replies but the reason I used `is not` is because then another test fails if I use `!=`: `[1, None, 2, 1, 0, 0, 0] should equal [1, None, 2, False, 1, 0, 0]` is what fails along with the original one. When I use `is not` this test passes. – Marcelino Velasquez Jul 07 '20 at 20:49