Is the iteration protocol used when indexing a range object?












5















Since the range object produces values on demand, does it mean that anytime a range is indexed, the iteration protocol is invoked up to that index?



What I mean is when:



>>> R = range(1,11)
>>> print(R[5])
6


Since R[5] isn't stored in memory, is it calculated every time by creating a new iterator? If not, how is it possible to index a range object?










share|improve this question





























    5















    Since the range object produces values on demand, does it mean that anytime a range is indexed, the iteration protocol is invoked up to that index?



    What I mean is when:



    >>> R = range(1,11)
    >>> print(R[5])
    6


    Since R[5] isn't stored in memory, is it calculated every time by creating a new iterator? If not, how is it possible to index a range object?










    share|improve this question



























      5












      5








      5


      0






      Since the range object produces values on demand, does it mean that anytime a range is indexed, the iteration protocol is invoked up to that index?



      What I mean is when:



      >>> R = range(1,11)
      >>> print(R[5])
      6


      Since R[5] isn't stored in memory, is it calculated every time by creating a new iterator? If not, how is it possible to index a range object?










      share|improve this question
















      Since the range object produces values on demand, does it mean that anytime a range is indexed, the iteration protocol is invoked up to that index?



      What I mean is when:



      >>> R = range(1,11)
      >>> print(R[5])
      6


      Since R[5] isn't stored in memory, is it calculated every time by creating a new iterator? If not, how is it possible to index a range object?







      python python-3.x indexing python-internals






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 22 '18 at 11:30









      Alex Riley

      81.7k26162166




      81.7k26162166










      asked Nov 21 '18 at 22:45









      masiewpaomasiewpao

      84110




      84110
























          2 Answers
          2






          active

          oldest

          votes


















          5














          No iterator is created here, and no iteration occurs. The range object is implemented such that Python computes the value of R[5] on-demand in constant time.1



          If the index i is not negative, the computation boils down to:



          i * step + start


          So in the case of your code R[5], this would be 5*1 + 1 which is 6.



          If the index i is negative, the length of R is added to i first, and then the value is computed as before:



          (i + len(R)) * step + start




          Python-internals



          When you write R[5], this Python syntax is eventually translated into a call to PyObject_GetItem, which inspects the object R to see how it should proceed to find the item at index 5.



          PyObject_GetItem first checks the tp_as_mapping slot of the range type. This is not null; it holds a reference to a struct called range_as_mapping. PyObject_GetItem then checks to see what is in the mp_subscript field of this struct:



          static PyMappingMethods range_as_mapping = {
          (lenfunc)range_length, /* mp_length */
          (binaryfunc)range_subscript, /* mp_subscript */
          (objobjargproc)0, /* mp_ass_subscript */
          };


          As you can see in the snippet above, it finds the range_subscript function occupying the mp_subscript field.2



          Now range_subscript inspects the arguments it was passed (R and 5) to decide if a single index or a slice was requested. The integer 5 means that just a single index is needed and so the function delegates the computation of the value to compute_range_item. This function performs the computation to return the integer 6 as outlined in the first part of this answer.





          1 I have assumed you are using CPython: other Python implementations may implement the range object differently.



          2 If you were to call len(R), you can see the internal function in mp_length that is called to compute the length of R (cf. Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?).






          share|improve this answer


























          • In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

            – lvc
            Nov 22 '18 at 11:43



















          -1














          Nope. It is not.



          However range supports both iteration protocol and indexing (through getitem)






          share|improve this answer



















          • 1





            Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

            – masiewpao
            Nov 22 '18 at 9:50











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421479%2fis-the-iteration-protocol-used-when-indexing-a-range-object%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          5














          No iterator is created here, and no iteration occurs. The range object is implemented such that Python computes the value of R[5] on-demand in constant time.1



          If the index i is not negative, the computation boils down to:



          i * step + start


          So in the case of your code R[5], this would be 5*1 + 1 which is 6.



          If the index i is negative, the length of R is added to i first, and then the value is computed as before:



          (i + len(R)) * step + start




          Python-internals



          When you write R[5], this Python syntax is eventually translated into a call to PyObject_GetItem, which inspects the object R to see how it should proceed to find the item at index 5.



          PyObject_GetItem first checks the tp_as_mapping slot of the range type. This is not null; it holds a reference to a struct called range_as_mapping. PyObject_GetItem then checks to see what is in the mp_subscript field of this struct:



          static PyMappingMethods range_as_mapping = {
          (lenfunc)range_length, /* mp_length */
          (binaryfunc)range_subscript, /* mp_subscript */
          (objobjargproc)0, /* mp_ass_subscript */
          };


          As you can see in the snippet above, it finds the range_subscript function occupying the mp_subscript field.2



          Now range_subscript inspects the arguments it was passed (R and 5) to decide if a single index or a slice was requested. The integer 5 means that just a single index is needed and so the function delegates the computation of the value to compute_range_item. This function performs the computation to return the integer 6 as outlined in the first part of this answer.





          1 I have assumed you are using CPython: other Python implementations may implement the range object differently.



          2 If you were to call len(R), you can see the internal function in mp_length that is called to compute the length of R (cf. Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?).






          share|improve this answer


























          • In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

            – lvc
            Nov 22 '18 at 11:43
















          5














          No iterator is created here, and no iteration occurs. The range object is implemented such that Python computes the value of R[5] on-demand in constant time.1



          If the index i is not negative, the computation boils down to:



          i * step + start


          So in the case of your code R[5], this would be 5*1 + 1 which is 6.



          If the index i is negative, the length of R is added to i first, and then the value is computed as before:



          (i + len(R)) * step + start




          Python-internals



          When you write R[5], this Python syntax is eventually translated into a call to PyObject_GetItem, which inspects the object R to see how it should proceed to find the item at index 5.



          PyObject_GetItem first checks the tp_as_mapping slot of the range type. This is not null; it holds a reference to a struct called range_as_mapping. PyObject_GetItem then checks to see what is in the mp_subscript field of this struct:



          static PyMappingMethods range_as_mapping = {
          (lenfunc)range_length, /* mp_length */
          (binaryfunc)range_subscript, /* mp_subscript */
          (objobjargproc)0, /* mp_ass_subscript */
          };


          As you can see in the snippet above, it finds the range_subscript function occupying the mp_subscript field.2



          Now range_subscript inspects the arguments it was passed (R and 5) to decide if a single index or a slice was requested. The integer 5 means that just a single index is needed and so the function delegates the computation of the value to compute_range_item. This function performs the computation to return the integer 6 as outlined in the first part of this answer.





          1 I have assumed you are using CPython: other Python implementations may implement the range object differently.



          2 If you were to call len(R), you can see the internal function in mp_length that is called to compute the length of R (cf. Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?).






          share|improve this answer


























          • In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

            – lvc
            Nov 22 '18 at 11:43














          5












          5








          5







          No iterator is created here, and no iteration occurs. The range object is implemented such that Python computes the value of R[5] on-demand in constant time.1



          If the index i is not negative, the computation boils down to:



          i * step + start


          So in the case of your code R[5], this would be 5*1 + 1 which is 6.



          If the index i is negative, the length of R is added to i first, and then the value is computed as before:



          (i + len(R)) * step + start




          Python-internals



          When you write R[5], this Python syntax is eventually translated into a call to PyObject_GetItem, which inspects the object R to see how it should proceed to find the item at index 5.



          PyObject_GetItem first checks the tp_as_mapping slot of the range type. This is not null; it holds a reference to a struct called range_as_mapping. PyObject_GetItem then checks to see what is in the mp_subscript field of this struct:



          static PyMappingMethods range_as_mapping = {
          (lenfunc)range_length, /* mp_length */
          (binaryfunc)range_subscript, /* mp_subscript */
          (objobjargproc)0, /* mp_ass_subscript */
          };


          As you can see in the snippet above, it finds the range_subscript function occupying the mp_subscript field.2



          Now range_subscript inspects the arguments it was passed (R and 5) to decide if a single index or a slice was requested. The integer 5 means that just a single index is needed and so the function delegates the computation of the value to compute_range_item. This function performs the computation to return the integer 6 as outlined in the first part of this answer.





          1 I have assumed you are using CPython: other Python implementations may implement the range object differently.



          2 If you were to call len(R), you can see the internal function in mp_length that is called to compute the length of R (cf. Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?).






          share|improve this answer















          No iterator is created here, and no iteration occurs. The range object is implemented such that Python computes the value of R[5] on-demand in constant time.1



          If the index i is not negative, the computation boils down to:



          i * step + start


          So in the case of your code R[5], this would be 5*1 + 1 which is 6.



          If the index i is negative, the length of R is added to i first, and then the value is computed as before:



          (i + len(R)) * step + start




          Python-internals



          When you write R[5], this Python syntax is eventually translated into a call to PyObject_GetItem, which inspects the object R to see how it should proceed to find the item at index 5.



          PyObject_GetItem first checks the tp_as_mapping slot of the range type. This is not null; it holds a reference to a struct called range_as_mapping. PyObject_GetItem then checks to see what is in the mp_subscript field of this struct:



          static PyMappingMethods range_as_mapping = {
          (lenfunc)range_length, /* mp_length */
          (binaryfunc)range_subscript, /* mp_subscript */
          (objobjargproc)0, /* mp_ass_subscript */
          };


          As you can see in the snippet above, it finds the range_subscript function occupying the mp_subscript field.2



          Now range_subscript inspects the arguments it was passed (R and 5) to decide if a single index or a slice was requested. The integer 5 means that just a single index is needed and so the function delegates the computation of the value to compute_range_item. This function performs the computation to return the integer 6 as outlined in the first part of this answer.





          1 I have assumed you are using CPython: other Python implementations may implement the range object differently.



          2 If you were to call len(R), you can see the internal function in mp_length that is called to compute the length of R (cf. Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?).







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 22 '18 at 11:36

























          answered Nov 22 '18 at 11:29









          Alex RileyAlex Riley

          81.7k26162166




          81.7k26162166













          • In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

            – lvc
            Nov 22 '18 at 11:43



















          • In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

            – lvc
            Nov 22 '18 at 11:43

















          In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

          – lvc
          Nov 22 '18 at 11:43





          In addition to these C-level functions, it might be worth mentioning the Python-level __getitem__ and __len__, as well as the sequence protocol.

          – lvc
          Nov 22 '18 at 11:43













          -1














          Nope. It is not.



          However range supports both iteration protocol and indexing (through getitem)






          share|improve this answer



















          • 1





            Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

            – masiewpao
            Nov 22 '18 at 9:50
















          -1














          Nope. It is not.



          However range supports both iteration protocol and indexing (through getitem)






          share|improve this answer



















          • 1





            Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

            – masiewpao
            Nov 22 '18 at 9:50














          -1












          -1








          -1







          Nope. It is not.



          However range supports both iteration protocol and indexing (through getitem)






          share|improve this answer













          Nope. It is not.



          However range supports both iteration protocol and indexing (through getitem)







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 '18 at 2:01









          ealfieealfie

          1




          1








          • 1





            Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

            – masiewpao
            Nov 22 '18 at 9:50














          • 1





            Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

            – masiewpao
            Nov 22 '18 at 9:50








          1




          1





          Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

          – masiewpao
          Nov 22 '18 at 9:50





          Hi thanks for the response! I had a look at the docs for getitem but I am not sure I understand it. If it equates to using self[key] for an object, isn't there still the problem of knowing the value in a virtual sequence (since it's not stored in memory)?

          – masiewpao
          Nov 22 '18 at 9:50


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421479%2fis-the-iteration-protocol-used-when-indexing-a-range-object%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Tangent Lines Diagram Along Smooth Curve

          Yusuf al-Mu'taman ibn Hud

          Zucchini