I just read PEP 207 a proposal for rich comparisons that allow you to write this kind of comparisons

>>> 1 < 2 < 3
True
>>> 2 < 3 < 2
False

This comparisons have the same meaning as in mathematics rather than the meaning in C. The previous code is equivalent to

>>> 1 < 2 and 2 < 3
True

In C, the results are not really what a mathematician expects. Here is a C snippet for demonstration:

int test1() {
    return 1 < 2 < 3;
} /* return 1 */
 
int test2() {
    return 2 < 3 < 2;
} /* return 1 */
 
int test3() {
    return 1 < 3 < 0;
} /* return 0*/

Following operators priority, the "evaluation" of 2 < 3 < 2 is equivalent to (2 < 3) < 2. Evaluation of (2 < 3) return 1, then 1 < 2 return 1.

Returning to the Python code, the two version are exactly equivalent when inside expression are side-effect free. In fact the inside expressions are evaluated only one time using chained comparison and two times when you write the "and" version.

# Function using a local variable for c-static-like variable hack
def mop(m=[1]):
    m[0] += 1
    return m[0]
1 < mop() < 3 # True 

First call to "mop" return 2.

def mop(m=[1]):
    m[0] += 1
    return m[0]
1 < mop() and mop() < 3 # False 

First call to "mop" return 2, and the second return 3. 3 < 3 is False, the "and" conclude ;). From the page PythonSpeed in the official Python wiki, chained comparisons are faster than the "and" version.