Python Chained Comparisons Magic
<p>A friend brought this to my attention, and after I pointed out an oddity, we're both confused.</p>

<p>Python's docs, say, and have said since at least 2.5.1 (haven't checked further back:</p>

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

<p>Our confusion lies in the meaning of "y is evaluated only once".</p>

<p>Given a simple but contrived class:</p>

<pre><code>class Magic(object):
    def __init__(self, name, val):
     self.name = name
     self.val = val
    def __lt__(self, other):
     print("Magic: Called lt on {0}".format(self.name))
     if self.val &lt; other.val:
      return True
     else:
      return False
    def __le__(self, other):
     print("Magic: Called le on {0}".format(self.name))
     if self.val &lt;= other.val:
      return True
     else:
      return False
</code></pre>

<p>We can produce this result:</p>

<pre><code>&gt;&gt;&gt; x = Magic("x", 0)
&gt;&gt;&gt; y = Magic("y", 5)
&gt;&gt;&gt; z = Magic("z", 10)
&gt;&gt;&gt; 
&gt;&gt;&gt; if x &lt; y &lt;= z:
...     print ("More magic.")
... 
Magic: Called lt on x
Magic: Called le on y
More magic.
&gt;&gt;&gt;
</code></pre>

<p>This certainly <em>looks</em> like 'y' is, in a traditional sense "evaluated" twice -- once when <code>x.__lt__(y)</code> is called and performs a comparison on it, and once when <code>y.__le__(z)</code> is called.</p>

<p>So with this in mind, what exactly do the Python docs mean when they say "y is evaluated only once"?</p>
