How come regex match objects aren't iterable even though they implement __getitem__?
Clash Royale CLAN TAG#URR8PPP
up vote
11
down vote
favorite
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
 |Â
show 3 more comments
up vote
11
down vote
favorite
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
I can't even seem to subscriptmatch
...
â Sweeper
53 mins ago
@SweeperMatch.__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
 |Â
show 3 more comments
up vote
11
down vote
favorite
up vote
11
down vote
favorite
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
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
python iterable
asked 1 hour ago
Aran-Fey
20.1k52862
20.1k52862
I can't even seem to subscriptmatch
...
â Sweeper
53 mins ago
@SweeperMatch.__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
 |Â
show 3 more comments
I can't even seem to subscriptmatch
...
â Sweeper
53 mins ago
@SweeperMatch.__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
 |Â
show 3 more comments
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
.
add a comment |Â
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
.
add a comment |Â
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
.
add a comment |Â
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
.
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
.
edited 1 min ago
answered 29 mins ago
Antti Haapala
73.7k16138184
73.7k16138184
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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