manoelpqueiroz
manoelpqueiroz

Reputation: 637

Are there relevant iterables with no length in Python?

In Luciano Ramalho's Fluent Python, an iterable is defined as an object in which the __iter__ method is implemented, with no additional characteristics.

I am currently working out a tutorial for laymen in which I am trying to chunk the core concepts of Python to make programming more manageable for newcomers.

I find it easier to explain iterables and their utility for these people when I associate these objects with the concept of "size" (thus also length). By saying that "iterables are objects that have length" and thus tying in with the len function, I am able to naturally evolve the concept of loops and iteration with commonly used types such as the Standard Library list, dict, tuple, str, as well as numpy.ndarray, pandas.Series and pandas.DataFrame.

However, since now I know about the sole necessity for the __iter__ method, there can be cases where the analogy with len fails. Ramalho even provides an impromptu example in his book:

import re
import reprlib

RE_WORD = re.compile(r'\w+')


class Sentence:

    def __init__(self, text):
        self.text = text

    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)

    def __iter__(self):
        for match in RE_WORD.finditer(self.text):
            yield match.group()

As expected, any instance of Sentence is an iterable (I can use for loops), but len(Sentence('an example')) will raise a TypeError.

Since all the aforementioned objects are iterables and have a __len__ method implemented, I want to know if there are relevant objects in Python which are iterables (__iter__), but do not have lengths (__len__) so if I can determine whether I just add a footnote to my tutorial or work out a different analogy.

Upvotes: 4

Views: 533

Answers (2)

superb rain
superb rain

Reputation: 5521

Iterators are ubiquitous iterables that usually don't offer a length:

>>> len(iter('foo'))
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    len(iter('foo'))
TypeError: object of type 'str_iterator' has no len()
>>> len(iter((1, 2, 3)))
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    len(iter((1, 2, 3)))
TypeError: object of type 'tuple_iterator' has no len()
>>> len(iter([1, 2, 3]))
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    len(iter([1, 2, 3]))
TypeError: object of type 'list_iterator' has no len()

Upvotes: 1

syntonym
syntonym

Reputation: 7384

A file has no length:

>>> with open("test") as f:
...    print(len(f))

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type '_io.TextIOWrapper' has no len()

Iterating through a file like that in open iterates over lines, i.e. chunks of text delimited by newline characters. To know how many lines there are, the file would have to be read entirely and then iterated through - depending on the size of the file this could take a long time or the computer could run out of RAM.

Upvotes: 5

Related Questions