title: Numpy performance gap between len(arr) and arr.shape[0]
body: <p>I've found that <code>len(arr)</code> is almost twice as fast as <code>arr.shape[0]</code> and am wondering why.</p>
  
  <p>I am using Python 3.5.2, Numpy 1.14.2, IPython 6.3.1</p>
  
  <p>The below code demonstrates this:</p>
  
  <pre><code>arr = np.random.randint(1, 11, size=(3, 4, 5))
  
  %timeit len(arr)
  # 62.6 ns ± 0.239 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  
  %timeit arr.shape[0]
  # 102 ns ± 0.163 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  </code></pre>
  
  <p>I've also done some more tests for comparison:</p>
  
  <pre><code>class Foo():
      def __init__(self):
          self.shape = (3, 4, 5)        
  
  foo = Foo()
  
  %timeit arr.shape
  # 75.6 ns ± 0.107 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  
  %timeit foo.shape
  # 61.2 ns ± 0.281 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  
  %timeit foo.shape[0]
  # 78.6 ns ± 1.03 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  </code></pre>
  
  <p>So I have two questions:</p>
  
  <p>1) Why does <code>len(arr)</code> works faster than <code>arr.shape[0]</code>? (I would have thought <code>len</code> would be slower because of the function call)</p>
  
  <p>2) Why does <code>foo.shape[0]</code> work faster than <code>arr.shape[0]</code>? (In other words, what overhead does do numpy arrays incur in this case?)</p>