Given 2 int values, return True if one is negative and other is positive

Your code doesn't work as intended because != takes higher precedence than a < 0 and b < 0. As itzmeontv suggests in his answer, you can simply decide the precedence yourself by surrounding logical components with parentheses:

(a < 0) != (b < 0)

Your code attempts to evaluate a < (0 != b) < 0

[EDIT]

As tzaman rightly points out, the operators have the same precedence, but your code is attempting to evaluate (a < 0) and (0 != b) and (b < 0). Surrounding your logical components with parentheses will resolve this:

(a < 0) != (b < 0)

Operator precedence: https://docs.python.org/3/reference/expressions.html#operator-precedence

Comparisons (i.a. chaining): https://docs.python.org/3/reference/expressions.html#not-in


All comparison operators in Python have the same precedence. In addition, Python does chained comparisons. Thus,

(a < 0 != b < 0)

breaks down as:

(a < 0) and (0 != b) and (b < 0)

If any one of these is false, the total result of the expression will be False.

What you want to do is evaluate each condition separately, like so:

(a < 0) != (b < 0)

Other variants, from comments:

(a < 0) is not (b < 0) # True and False are singletons so identity-comparison works

(a < 0) ^ (b < 0) # bitwise-xor does too, as long as both sides are boolean

(a ^ b < 0) # or you could directly bitwise-xor the integers; 
            # the sign bit will only be set if your condition holds
            # this one fails when you mix ints and floats though

(a * b < 0) # perhaps most straightforward, just multiply them and check the sign

You can use this

return (a < 0) != (b < 0)

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

So it becomes

(a < 0) and (0 != b) and (b < 0)

See https://docs.python.org/3/reference/expressions.html#not-in