title: What is the operator precedence when writing a double inequality in Python (explicitly in the code, and how can this be overridden for arrays?)
body: <p>What is the specific code, in order, being executed when I ask for something like</p>
  
  <pre><code>&gt;&gt;&gt; 1 &lt;= 3 &gt;= 2
  True
  </code></pre>
  
  <p>If both have equal precedence and it's just the order of their evaluation, why does the second inequality function as <code>(3 &gt;= 2)</code> instead of <code>(True &gt;= 2)</code></p>
  
  <p>Consider for example the difference between these</p>
  
  <pre><code>&gt;&gt;&gt; (1 &lt; 3) &lt; 2
  True
  
  &gt;&gt;&gt; 1 &lt; 3 &lt; 2
  False
  </code></pre>
  
  <p>Is it just a pure syntactical short-cut hard-coded into Python to expand the second as the <code>and</code> of the two statements?</p>
  
  <p>Could I change this behavior for a class, such that <code>a &lt;= b &lt;= c</code> gets expanded to something different? It's looking like the following is the case</p>
  
  <pre><code>a (logical operator) b (logical operator) c 
      --&gt; (a logical operator b) and (b logical operator c)
  </code></pre>
  
  <p>but the real question is how this gets implemented in code.</p>
  
  <p>I'm curious so that I can replicate this kind of <code>__lt__</code> and <code>__gt__</code> behavior in some of my own classes, but I am confused about how this is accomplished holding the middle argument constant.</p>
  
  <p>Here's a specific example:</p>
  
  <pre><code>&gt;&gt;&gt; import numpy as np
  
  &gt;&gt;&gt; tst = np.asarray([1,2,3,4,5,6])
  
  &gt;&gt;&gt; 3 &lt;= tst
  array([False, False,  True,  True,  True,  True], dtype=bool)
  
  &gt;&gt;&gt; 3 &lt;= tst &lt;= 5
  ---------------------------------------------------------------------------
  ValueError                                Traceback (most recent call last)
  /home/ely/&lt;ipython-input-135-ac909818f2b1&gt; in &lt;module&gt;()
  ----&gt; 1 3 &lt;= tst &lt;= 5
  
  ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
  </code></pre>
  
  <p>It would be nice to override this so that it "just works" with arrays too, like this:</p>
  
  <pre><code>&gt;&gt;&gt; np.logical_and(3 &lt;= tst, tst &lt;= 5)
  array([False, False,  True,  True,  True,  False], dtype=bool)
  </code></pre>
  
  <p><strong>Added for clarification</strong></p>
  
  <p>In the comments it is indicated that I did a poor job of explaining the question. Here's some clarifying remarks:</p>
  
  <p>1) I am <em>not</em> looking for a simple explanation of the fact that the interpreter pops an <code>and</code> in between the two chained inequalities. I already knew that and said so above.</p>
  
  <p>2) For an analogy to what I want to do, consider the <code>with</code> statement (<a href="http://www.python.org/dev/peps/pep-0343/" rel="noreferrer">link</a>). The following:</p>
  
  <pre><code>with MyClass(some_obj) as foo:
      do_stuff()
  </code></pre>
  
  <p>unpacks into </p>
  
  <pre><code>foo = MyClass(some_obj)
  foo.__enter__()
  try:
      do_stuff()
  finally:
      foo.__exit__()
  </code></pre>
  
  <p>So by writing <code>MyClass</code> appropriately, I can do many special things inside of the <code>with</code> statement.</p>
  
  <p>I am asking whether there is a similar code unpacking of the chained inequality by which I can intercept what it's doing and redirect it to use array-style logical operators instead <em>just for the classes I care about</em>.</p>
  
  <p>I feel this is very clear from my question, especially the example, but hopefully this makes it more clear.</p>