Looking at the disassembly (the bytes codes) it is obvious why 0 < 0 == 0 is False.
Here is an analysis of this expression:
>>>import dis
>>>def f():
...    0 < 0 == 0
>>>dis.dis(f)
  2      0 LOAD_CONST               1 (0)
         3 LOAD_CONST               1 (0)
         6 DUP_TOP
         7 ROT_THREE
         8 COMPARE_OP               0 (<)
        11 JUMP_IF_FALSE_OR_POP    23
        14 LOAD_CONST               1 (0)
        17 COMPARE_OP               2 (==)
        20 JUMP_FORWARD             2 (to 25)
   >>   23 ROT_TWO
        24 POP_TOP
   >>   25 POP_TOP
        26 LOAD_CONST               0 (None)
        29 RETURN_VALUE
Notice lines 0-8: These lines check if 0 < 0 which obviously returns False onto the python stack.
Now notice line 11: JUMP_IF_FALSE_OR_POP 23
This means that if 0 < 0 returns False perform a jump to line 23.
Now, 0 < 0 is False, so the jump is taken, which leaves the stack with a False which is the return value for the whole expression 0 < 0 == 0, even though the == 0 part isn't even checked.
So, to conclude, the answer is like said in other answers to this question.
0 < 0 == 0 has a special meaning. The compiler evaluates this to two terms: 0 < 0 and 0 == 0. As with any complex boolean expressions with and between them, if the first fails then the second one isn't even checked.
Hopes this enlightens things up a bit, and I really hope that the method I used to analyse this unexpected behavior will encourage others to try the same in the future.