<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Guy Goldberg</title>
    <description>The latest articles on DEV Community by Guy Goldberg (@guy_gold).</description>
    <link>https://dev.to/guy_gold</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36471%2F42a01665-5a2b-462a-a378-f80fcfd2482d.jpeg</url>
      <title>DEV Community: Guy Goldberg</title>
      <link>https://dev.to/guy_gold</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guy_gold"/>
    <language>en</language>
    <item>
      <title>xrange vs. range vs. range</title>
      <dc:creator>Guy Goldberg</dc:creator>
      <pubDate>Fri, 19 Jan 2018 13:01:21 +0000</pubDate>
      <link>https://dev.to/guy_gold/xrange-vs-range-vs-range-kd4</link>
      <guid>https://dev.to/guy_gold/xrange-vs-range-vs-range-kd4</guid>
      <description>&lt;h1&gt;
  
  
  A simple question
&lt;/h1&gt;

&lt;p&gt;While I was teaching a class about iterators and generators, a student asked me a question that didn't seem so interesting at first. "What is faster - xrange or range?". I tried to explain to him that in many cases it's better to use xrange instead of range - but because of the lower memory usage, and not because of run time. He continued: "Yes, I get it. But which one is faster?".&lt;br&gt;
Well, it's pretty obvious that building a list with range takes more time than calling xrange - since when calling xrange, no real list is built. So to phrase it more precisely, the question is:&lt;br&gt;
What is faster - calling next of an iterator over a list object, or calling next of an iterator of an xrange object?&lt;/p&gt;
&lt;h1&gt;
  
  
  A simple answer?
&lt;/h1&gt;

&lt;p&gt;I had to think about it for a bit. Before looking at the documentation or source code, I tried to think what is my intuition about it.&lt;br&gt;
Both operations suppose to be pretty fast, compared to other basic operations (like building a list with range).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting the next object in a list is basically accessing an array in some specific index (and increasing that index)&lt;/li&gt;
&lt;li&gt;Getting the next object of a xrange object is basically increasing some number, and returning it. Again, a very simple operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what is faster? Direct memory access or a simple addition?&lt;br&gt;
I thought that maybe the addition (xrange) would be a bit faster, but not by much.&lt;/p&gt;
&lt;h1&gt;
  
  
  RTFM
&lt;/h1&gt;

&lt;p&gt;What does the documentation of xrange have to say about it?&lt;br&gt;
Well, according to Docstring of xrange, it is slightly faster than range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="err"&gt;?&lt;/span&gt;
&lt;span class="n"&gt;Docstring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nf"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;
&lt;span class="nf"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;


&lt;span class="n"&gt;Like&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;instead&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;returning&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt;
&lt;span class="n"&gt;generates&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;demand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;  &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;looping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;
&lt;span class="n"&gt;slightly&lt;/span&gt; &lt;span class="n"&gt;faster&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;efficient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the Docstring doesn't say exactly what is faster about range. So we have to guess that they are addressing calling the next method (iterating over the xrange)&lt;/p&gt;

&lt;p&gt;But, the "formal" documentation of python, doesn't say anything explicitly about the speed of xrange:&lt;/p&gt;

&lt;p&gt;xrange(stop)&lt;br&gt;
xrange(start, stop[, step])&lt;br&gt;
This function is very similar to range(), but returns an xrange object instead of a list. This is an opaque sequence type which yields the same values as the corresponding list, without actually storing them all simultaneously. The advantage of xrange() over range() is minimal (since xrange() still has to create the values when asked for them) except when a very large range is used on a memory-starved machine or when all of the range’s elements are never used (such as when the loop is usually terminated with break). For more information on xrange objects, see XRange Type and Sequence Types — str, unicode, list, tuple, bytearray, buffer, xrange.&lt;/p&gt;

&lt;p&gt;You can see that documentation here - &lt;a href="https://docs.python.org/2/library/functions.html#xrange" rel="noopener noreferrer"&gt;https://docs.python.org/2/library/functions.html#xrange&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Run it!
&lt;/h1&gt;

&lt;p&gt;One of the many things I like about Python is that it is really easy to try things out. If you want to know what is faster, just run the code, and see what is faster!&lt;br&gt;
We want to eliminate the time building the list with range and focus just on the iteration itself.&lt;br&gt;
ipython has a very nice feature for checking the run time of methods - %timeit. We can use it with next of list iterator / xrange iterator and see which one is faster.&lt;br&gt;
We will use a list /xrange of size 10,000,000 for the test. We will also need to limit the number of tests that %timeit performs, so we won't hit StopIteration exception (the end of the list / xrange).&lt;br&gt;
Here are the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;list_iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;list_iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;68.7&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;xrange_iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;xrange_iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;65.9&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems a bit faster, right? By about 5%&lt;br&gt;
But the results are not so consistent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;xrange_iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;xrange_iterator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;71.6&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the xrange is slower!&lt;br&gt;
The source of differences is probably my running environment (a pretty old Ubuntu 14.04 VM, with just 1GB of memory and a single CPU).&lt;br&gt;
The important part is that it doesn't seem like there is a big different between the speed of xrange and range in Python 2.7.&lt;/p&gt;
&lt;h1&gt;
  
  
  What about Python 3?
&lt;/h1&gt;

&lt;p&gt;Well, in Python 3 xranges were removed completely from the language. Now range objects behave like the old and beloved xranges, and they return an object which you can iterate on - but which is not a list.&lt;br&gt;
So you would think that the new range objects will be faster than the old xrange objects, right?&lt;br&gt;
Let's check it out.&lt;br&gt;
Remember that .next was also removed from Python 3, and now we need to call next(iterator) instead of iterator.next().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;range_iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;range_iterator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;111&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;7.63&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="nf"&gt;loop &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's above 110 ns for an operation, instead of ~70 ns in Python 2!&lt;br&gt;
And as with Python 2, it seems that iterating over lists takes similar time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;list_iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_iterator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;95.7&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;7.13&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="nf"&gt;loop &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's even a bit &lt;em&gt;faster&lt;/em&gt; then xrange, but still - it's 50% slower than iteration in Python 2.&lt;/p&gt;

&lt;p&gt;This is actually a known phenomenon with Python 3.&lt;br&gt;
You can read some possible explanation for it here - &lt;a href="https://stackoverflow.com/questions/23453133/is-there-a-reason-python-3-enumerates-slower-than-python-2" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/23453133/is-there-a-reason-python-3-enumerates-slower-than-python-2&lt;/a&gt;&lt;br&gt;
(though, In my opinion, this answer doesn't seem correct - since we use only small numbers - lower than sys.maxint)&lt;/p&gt;
&lt;h1&gt;
  
  
  High numbers
&lt;/h1&gt;

&lt;p&gt;The answer in the above stack overflow link made me wonder - what will happen with very high numbers? Would range and list(range) still have similar speeds?&lt;br&gt;
My intuition said that the results will be similar to the results we saw before - around 100 ns for each call to next.&lt;br&gt;
But again - the best way to find things out is to try!&lt;br&gt;
So let's check it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;list_iterator_high_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_iterator_high_numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;97&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;12.1&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="nf"&gt;loop &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, the result for lists is very similar to the results before. No surprise here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;range_iterator_high_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;range_iterator_high_numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;204&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="mf"&gt;9.15&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="nf"&gt;loop &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="err"&gt;±&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this is a surprise! Iterating on high numbers with range is &lt;em&gt;much&lt;/em&gt; slower than iterating over low numbers. Calling next takes on average 100% more time!&lt;/p&gt;

&lt;p&gt;Why does that happen?&lt;br&gt;
I couldn't find any hint in the documentation, so I had to take the next step and&lt;/p&gt;

&lt;h1&gt;
  
  
  Read the source code
&lt;/h1&gt;

&lt;p&gt;Another great thing about Python is that you can just simply read its source code. If you want to understand something more thoroughly, or if you are just a bit curious, you can read the code itself!&lt;br&gt;
The relevant module we want to look at is Objects/rangeobject.c, which contains the implementation of range objects in Python 3.&lt;br&gt;
You can find it here - &lt;a href="https://github.com/python/cpython/blob/master/Objects/rangeobject.c" rel="noopener noreferrer"&gt;https://github.com/python/cpython/blob/master/Objects/rangeobject.c&lt;/a&gt;&lt;br&gt;
It's pretty easy to find the code of the "next" method, which is the method we are interested in:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ezs2u83t7mgtkc81bkw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ezs2u83t7mgtkc81bkw.PNG" alt="rangeiter_next" width="703" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code is pretty straight-forward. If the range didn't reach its end yet, increase the index by one, multiply it by "step", add to "start" and return the value as a Python long object. (The casting issue is not relevant to us now).&lt;br&gt;
It seems like an efficient code. Why is it less efficient for high numbers?&lt;br&gt;
But wait a second. It doesn't work for numbers which are "longer" than long at all!&lt;br&gt;
We just saw that range does support very high numbers, with more than 64 bits. long variables in C can only store numbers with up to 32 (or 64) bits. There must be some other code that handles the higher numbers.&lt;br&gt;
Well, in my first look I missed the comment just above that method:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2r2424an1y3uspwss2y7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2r2424an1y3uspwss2y7.PNG" alt="documentation of range Iterator" width="612" height="173"&gt;&lt;/a&gt;&lt;br&gt;
it clearly says that there's one implementation for C longs (the one that we just saw) and another implementation for Python ints.&lt;br&gt;
That method appears ~250 lines later:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7n1qtl2yfki4a4ip5v8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7n1qtl2yfki4a4ip5v8.PNG" alt="longarangeiter_next" width="603" height="701"&gt;&lt;/a&gt;&lt;br&gt;
Look at all that code. &lt;br&gt;
Instead of 3-4 basic arithmetic operations that we saw in rangeiter_next, here at longrangeiter_next there are much more complicated operations. You can't simply use "+" to add Python ints - you have to use PyNumber_Add. You can't use "*" to multiply the "index" and "step" - you have to use PyNumber_Multiple.&lt;br&gt;
No wonder that calling next takes more time for "longer than long" numbers - much more things are happening under the hood.&lt;br&gt;
But for the next method of regular lists, it doesn't matter what the values inside the list are - you don't need to do any "complicated" arithmetic operations like multiplying Python ints to get an item from a list.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final words
&lt;/h1&gt;

&lt;p&gt;So, what did we see here?&lt;br&gt;
We started with a simple question - what is faster, xrange or range? and we saw that the answer is not so obvious.&lt;br&gt;
We continued by comparing the speed of Python 2 and Python 3, and we were surprised to see that Python 3 is a bit slower in that area.&lt;br&gt;
Then we looked at ranges with high numbers and saw that they are much slower than "lower" ranges. We had to explore the Python source code to find out the reason for that.&lt;/p&gt;

&lt;p&gt;That's all for this post, I hope you enjoyed it.&lt;/p&gt;

</description>
      <category>python</category>
      <category>internals</category>
      <category>programming</category>
      <category>c</category>
    </item>
    <item>
      <title>5 Tips for interviewers</title>
      <dc:creator>Guy Goldberg</dc:creator>
      <pubDate>Fri, 17 Nov 2017 12:50:00 +0000</pubDate>
      <link>https://dev.to/guy_gold/5-tips-for-interviewers-3fh</link>
      <guid>https://dev.to/guy_gold/5-tips-for-interviewers-3fh</guid>
      <description>&lt;p&gt;Interviewing someone for your company is not an easy job. Sometimes you have to do it without any training. If you're lucky, in the first few interviews you will join someone experienced who will lead the interview. If you take your job seriously, you might want to read some tips and guidelines on how to conduct a great interview.&lt;br&gt;
After conducting hundreds of interviews, for various positions (Researchers, Developers, Team leaders and QA engineers), I collected the 5 most important tips, in my opinion, which might help you for any kind of interview.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Ask "Can you give me an example?"
&lt;/h1&gt;

&lt;p&gt;When the interviewee is saying something like "I was in charge of testing feature X", or "I developed many features", always ask him to give concrete examples. You will be amazed how people can talk with extreme confidence about things they did in a very general way, but once you ask them to give examples - you'll find out they don't really understand what they did.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Ask "What was your role in that project"?
&lt;/h1&gt;

&lt;p&gt;This is quite similar to the previous tip. Candidates sometimes describe really big projects, which seem impressive. In those cases, it's important to check what they actually did on that project. More often than not, you'll find out that the role the candidate had in the project is smaller than it seemed at first.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Try to make the candidate talk while he is thinking
&lt;/h1&gt;

&lt;p&gt;The number 1 tip that I give to candidates is to always talk while you think. In this way, the interviewer can understand better your thinking processes and might help you if you are not in the correct direction. From the interviewer perspective, many candidates don't follow that tip, and it is hard to know what they think. Simply ask them to talk and explain what they are thinking about. Even if they have ideas that they think are "bad", ask them to explain them. Sometimes they hit the correct solution to the question, but just don't say it to you since they think that there's some mistake in it. As an interviewer, you want to know that they found the solution, even if they didn't think it is correct.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Ask "Can you explain me an interesting bug that you encountered?"
&lt;/h1&gt;

&lt;p&gt;This is my favorite interview question. It gives you an opportunity to see how good the candidate can explain something technical, and how deep he understands technical issues. It also helps you to see if the candidate can identify what was important and what wasn't.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Don't have small-talks with your co-interviewer
&lt;/h1&gt;

&lt;p&gt;The interviewee is under a lot of stress and is trying to think. Yes, you might be bored, and yes, it is much more interesting to talk about what to eat for lunch than look at someone you don't know trying to solve a question you know. But you should respect the candidate, and you shouldn't disturb him&lt;/p&gt;

&lt;p&gt;What do you think about the tips in this article? Do you have any other tips for someone who begins to interview? Let me know if the article was useful to someone.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
