How come regex match objects aren't iterable even though they implement __getitem__?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
11
down vote

favorite
1












As you may know, implementing a __getitem__ method makes a class iterable:



class IterableDemo:
def __getitem__(self, index):
if index > 3:
raise IndexError

return index

demo = IterableDemo()
print(demo[2]) # 2
print(list(demo)) # [0, 1, 2, 3]


However, this doesn't hold true for regex match objects:



>>> import re
>>> match = re.match('(ab)c', 'abc')
>>> match[0]
'abc'
>>> match[1]
'ab'
>>> list(match)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '_sre.SRE_Match' object is not iterable


It's worth noting that this exception isn't thrown in the __iter__ method, because that method isn't even implemented:



>>> hasattr(match, '__iter__')
False


So, how is it possible to implement __getitem__ without making the class iterable?










share|improve this question





















  • I can't even seem to subscript match...
    – Sweeper
    53 mins ago










  • @Sweeper Match.__getitem__ was added in Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
    – DeepSpace
    51 mins ago











  • @DeepSpace Ah... I was using 3.5.
    – Sweeper
    51 mins ago










  • Possible duplicate of TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
    – Pedro Lobito
    50 mins ago






  • 1




    @PedroLobito But that has no explanation?
    – Li357
    49 mins ago














up vote
11
down vote

favorite
1












As you may know, implementing a __getitem__ method makes a class iterable:



class IterableDemo:
def __getitem__(self, index):
if index > 3:
raise IndexError

return index

demo = IterableDemo()
print(demo[2]) # 2
print(list(demo)) # [0, 1, 2, 3]


However, this doesn't hold true for regex match objects:



>>> import re
>>> match = re.match('(ab)c', 'abc')
>>> match[0]
'abc'
>>> match[1]
'ab'
>>> list(match)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '_sre.SRE_Match' object is not iterable


It's worth noting that this exception isn't thrown in the __iter__ method, because that method isn't even implemented:



>>> hasattr(match, '__iter__')
False


So, how is it possible to implement __getitem__ without making the class iterable?










share|improve this question





















  • I can't even seem to subscript match...
    – Sweeper
    53 mins ago










  • @Sweeper Match.__getitem__ was added in Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
    – DeepSpace
    51 mins ago











  • @DeepSpace Ah... I was using 3.5.
    – Sweeper
    51 mins ago










  • Possible duplicate of TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
    – Pedro Lobito
    50 mins ago






  • 1




    @PedroLobito But that has no explanation?
    – Li357
    49 mins ago












up vote
11
down vote

favorite
1









up vote
11
down vote

favorite
1






1





As you may know, implementing a __getitem__ method makes a class iterable:



class IterableDemo:
def __getitem__(self, index):
if index > 3:
raise IndexError

return index

demo = IterableDemo()
print(demo[2]) # 2
print(list(demo)) # [0, 1, 2, 3]


However, this doesn't hold true for regex match objects:



>>> import re
>>> match = re.match('(ab)c', 'abc')
>>> match[0]
'abc'
>>> match[1]
'ab'
>>> list(match)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '_sre.SRE_Match' object is not iterable


It's worth noting that this exception isn't thrown in the __iter__ method, because that method isn't even implemented:



>>> hasattr(match, '__iter__')
False


So, how is it possible to implement __getitem__ without making the class iterable?










share|improve this question













As you may know, implementing a __getitem__ method makes a class iterable:



class IterableDemo:
def __getitem__(self, index):
if index > 3:
raise IndexError

return index

demo = IterableDemo()
print(demo[2]) # 2
print(list(demo)) # [0, 1, 2, 3]


However, this doesn't hold true for regex match objects:



>>> import re
>>> match = re.match('(ab)c', 'abc')
>>> match[0]
'abc'
>>> match[1]
'ab'
>>> list(match)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '_sre.SRE_Match' object is not iterable


It's worth noting that this exception isn't thrown in the __iter__ method, because that method isn't even implemented:



>>> hasattr(match, '__iter__')
False


So, how is it possible to implement __getitem__ without making the class iterable?







python iterable






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 1 hour ago









Aran-Fey

20.1k52862




20.1k52862











  • I can't even seem to subscript match...
    – Sweeper
    53 mins ago










  • @Sweeper Match.__getitem__ was added in Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
    – DeepSpace
    51 mins ago











  • @DeepSpace Ah... I was using 3.5.
    – Sweeper
    51 mins ago










  • Possible duplicate of TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
    – Pedro Lobito
    50 mins ago






  • 1




    @PedroLobito But that has no explanation?
    – Li357
    49 mins ago
















  • I can't even seem to subscript match...
    – Sweeper
    53 mins ago










  • @Sweeper Match.__getitem__ was added in Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
    – DeepSpace
    51 mins ago











  • @DeepSpace Ah... I was using 3.5.
    – Sweeper
    51 mins ago










  • Possible duplicate of TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
    – Pedro Lobito
    50 mins ago






  • 1




    @PedroLobito But that has no explanation?
    – Li357
    49 mins ago















I can't even seem to subscript match...
– Sweeper
53 mins ago




I can't even seem to subscript match...
– Sweeper
53 mins ago












@Sweeper Match.__getitem__ was added in Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
– DeepSpace
51 mins ago





@Sweeper Match.__getitem__ was added in Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
– DeepSpace
51 mins ago













@DeepSpace Ah... I was using 3.5.
– Sweeper
51 mins ago




@DeepSpace Ah... I was using 3.5.
– Sweeper
51 mins ago












Possible duplicate of TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
– Pedro Lobito
50 mins ago




Possible duplicate of TypeError: '_sre.SRE_Match' object has no attribute '__getitem__'
– Pedro Lobito
50 mins ago




1




1




@PedroLobito But that has no explanation?
– Li357
49 mins ago




@PedroLobito But that has no explanation?
– Li357
49 mins ago












1 Answer
1






active

oldest

votes

















up vote
6
down vote



accepted










There are lies, damned lies and then there is Python documentation.



It is not enough to have a __getitem__ for a class implemented in C to be iterable. That is because there are actually 2 places in the PyTypeObject where the __getitem__ can be mapped to: tp_as_sequence and tp_as_mapping. Both have a slot for __getitem__ ([1], [2]).



Looking at the source of the SRE_Match, tp_as_sequence is initialized to NULL whereas tp_as_mapping is defined.



The iter() built-in function, if called with one argument, will call the PyObject_GetIter, which has the following code:



f = t->tp_iter;
if (f == NULL)
if (PySequence_Check(o))
return PySeqIter_New(o);
return type_error("'%.200s' object is not iterable", o);



It first checks the tp_iter slot (obviously NULL for _SRE_Match objects); and failing that, then if PySequence_Check returns true, a new sequence iterator, else a TypeError is raised.



PySequenceCheck first checks if the object is a dict or a dict subclass - and returns false in that case. Otherwise it returns the value of



s->ob_type->tp_as_sequence &&
s->ob_type->tp_as_sequence->sq_item != NULL;


and since s->ob_type->tp_as_sequence was NULL for a _SRE_Match instance, 0 will be returned, and PyObject_GetIter raises TypeError: '_sre.SRE_Match' object is not iterable.






share|improve this answer






















    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',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    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%2f52357560%2fhow-come-regex-match-objects-arent-iterable-even-though-they-implement-getite%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    6
    down vote



    accepted










    There are lies, damned lies and then there is Python documentation.



    It is not enough to have a __getitem__ for a class implemented in C to be iterable. That is because there are actually 2 places in the PyTypeObject where the __getitem__ can be mapped to: tp_as_sequence and tp_as_mapping. Both have a slot for __getitem__ ([1], [2]).



    Looking at the source of the SRE_Match, tp_as_sequence is initialized to NULL whereas tp_as_mapping is defined.



    The iter() built-in function, if called with one argument, will call the PyObject_GetIter, which has the following code:



    f = t->tp_iter;
    if (f == NULL)
    if (PySequence_Check(o))
    return PySeqIter_New(o);
    return type_error("'%.200s' object is not iterable", o);



    It first checks the tp_iter slot (obviously NULL for _SRE_Match objects); and failing that, then if PySequence_Check returns true, a new sequence iterator, else a TypeError is raised.



    PySequenceCheck first checks if the object is a dict or a dict subclass - and returns false in that case. Otherwise it returns the value of



    s->ob_type->tp_as_sequence &&
    s->ob_type->tp_as_sequence->sq_item != NULL;


    and since s->ob_type->tp_as_sequence was NULL for a _SRE_Match instance, 0 will be returned, and PyObject_GetIter raises TypeError: '_sre.SRE_Match' object is not iterable.






    share|improve this answer


























      up vote
      6
      down vote



      accepted










      There are lies, damned lies and then there is Python documentation.



      It is not enough to have a __getitem__ for a class implemented in C to be iterable. That is because there are actually 2 places in the PyTypeObject where the __getitem__ can be mapped to: tp_as_sequence and tp_as_mapping. Both have a slot for __getitem__ ([1], [2]).



      Looking at the source of the SRE_Match, tp_as_sequence is initialized to NULL whereas tp_as_mapping is defined.



      The iter() built-in function, if called with one argument, will call the PyObject_GetIter, which has the following code:



      f = t->tp_iter;
      if (f == NULL)
      if (PySequence_Check(o))
      return PySeqIter_New(o);
      return type_error("'%.200s' object is not iterable", o);



      It first checks the tp_iter slot (obviously NULL for _SRE_Match objects); and failing that, then if PySequence_Check returns true, a new sequence iterator, else a TypeError is raised.



      PySequenceCheck first checks if the object is a dict or a dict subclass - and returns false in that case. Otherwise it returns the value of



      s->ob_type->tp_as_sequence &&
      s->ob_type->tp_as_sequence->sq_item != NULL;


      and since s->ob_type->tp_as_sequence was NULL for a _SRE_Match instance, 0 will be returned, and PyObject_GetIter raises TypeError: '_sre.SRE_Match' object is not iterable.






      share|improve this answer
























        up vote
        6
        down vote



        accepted







        up vote
        6
        down vote



        accepted






        There are lies, damned lies and then there is Python documentation.



        It is not enough to have a __getitem__ for a class implemented in C to be iterable. That is because there are actually 2 places in the PyTypeObject where the __getitem__ can be mapped to: tp_as_sequence and tp_as_mapping. Both have a slot for __getitem__ ([1], [2]).



        Looking at the source of the SRE_Match, tp_as_sequence is initialized to NULL whereas tp_as_mapping is defined.



        The iter() built-in function, if called with one argument, will call the PyObject_GetIter, which has the following code:



        f = t->tp_iter;
        if (f == NULL)
        if (PySequence_Check(o))
        return PySeqIter_New(o);
        return type_error("'%.200s' object is not iterable", o);



        It first checks the tp_iter slot (obviously NULL for _SRE_Match objects); and failing that, then if PySequence_Check returns true, a new sequence iterator, else a TypeError is raised.



        PySequenceCheck first checks if the object is a dict or a dict subclass - and returns false in that case. Otherwise it returns the value of



        s->ob_type->tp_as_sequence &&
        s->ob_type->tp_as_sequence->sq_item != NULL;


        and since s->ob_type->tp_as_sequence was NULL for a _SRE_Match instance, 0 will be returned, and PyObject_GetIter raises TypeError: '_sre.SRE_Match' object is not iterable.






        share|improve this answer














        There are lies, damned lies and then there is Python documentation.



        It is not enough to have a __getitem__ for a class implemented in C to be iterable. That is because there are actually 2 places in the PyTypeObject where the __getitem__ can be mapped to: tp_as_sequence and tp_as_mapping. Both have a slot for __getitem__ ([1], [2]).



        Looking at the source of the SRE_Match, tp_as_sequence is initialized to NULL whereas tp_as_mapping is defined.



        The iter() built-in function, if called with one argument, will call the PyObject_GetIter, which has the following code:



        f = t->tp_iter;
        if (f == NULL)
        if (PySequence_Check(o))
        return PySeqIter_New(o);
        return type_error("'%.200s' object is not iterable", o);



        It first checks the tp_iter slot (obviously NULL for _SRE_Match objects); and failing that, then if PySequence_Check returns true, a new sequence iterator, else a TypeError is raised.



        PySequenceCheck first checks if the object is a dict or a dict subclass - and returns false in that case. Otherwise it returns the value of



        s->ob_type->tp_as_sequence &&
        s->ob_type->tp_as_sequence->sq_item != NULL;


        and since s->ob_type->tp_as_sequence was NULL for a _SRE_Match instance, 0 will be returned, and PyObject_GetIter raises TypeError: '_sre.SRE_Match' object is not iterable.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 1 min ago

























        answered 29 mins ago









        Antti Haapala

        73.7k16138184




        73.7k16138184



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52357560%2fhow-come-regex-match-objects-arent-iterable-even-though-they-implement-getite%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            Installing NextGIS Connect into QGIS 3?

            One-line joke