What is the difference between subscriptable and iterable objects ? What are the objects which are subscriptable but not iterable and vice versa?
P.s. Subscriptable are objects which contains other objects in it and iterators are subscriptable which can be iterated. But nothing more than this i can think of.
CodePudding user response:
What is the difference between subscriptable and iterable objects ?
subscriptable objects implement
__getitem__
and thus the evaluation of theobj[key]
syntax.iterable objects implement
__iter__
and thus support iteration.
What are the objects which are subscriptable but not iterable
An example is re.match()
which returns a subscriptable that is not iterable.
import re
m = re.match(r"\w (\w )", "Isaac Newton, physicist")
You then can do:
print(m[1]) # "Newton"
but this produces an exception:
for word in m: # TypeError: 're.Match' object is not iterable
print(word)
and vice versa?
An example is a set
, which supports iteration but not subscription. So you can do:
for x in set([42]):
print(x) # 42
...but this produces an error:
set([42])[0] # TypeError: 'set' object is not subscriptable
CodePudding user response:
As said by @juanpa.arrivillaga in his comment:
Subscriptable objects are objects that implement
__getitem__
. Iterable objects implement__iter__
so at the language level those concepts are not directly related
That being said, most common containers like lists or dictionnaries are both iterables and subscriptables. But a set
is an example of iterable and non subscriptable container, and the same, generators produce iterable and non subscriptable objects.
I have no common example for a substriptable but non iterable object, but it is easy to imagine a special class verifying that. The corner case is that if the subscripts can be integers, the object will not be a true iterable (cannot use iter
on it), but the for ... in ...
will still work by under the hood reverting to calling __getitem__
on successive integers
But here is a possible example (even if I cannot imagine a real world use case for that):
class SubscriptNonIter:
def __init__(self, count):
self._count = count
def __getitem__(self, key):
return ''.join(c for i, c in enumerate(key) if i % self._count == 0)
Example usage:
>>> x = SubscriptNonIter(2)
>>> x['abcd']
'ac'
>>> for i in x:
print(i)
Traceback (most recent call last):
File "...", line 1, in <module>
for i in x:
File "...", line 6, in __getitem__
return ''.join(c for i, c in enumerate(key) if i % self._count == 0)
TypeError: 'int' object is not iterable