Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper return value for __len__ for an object that acts as an infinite sequence

I am writing a python class that acts as an immutable, infinite sequence.

The class does not use a generator to access this infinite sequence, rather it generates a value for an arbitrary index in the sequence according to an algorithm within the __getitem__ method.

I am curious what the best way to handle the __len__ method of such an object is. Ideally, I would just return float("inf") through __len__. However, the len() function that calls an object's __len__ method behind the scenes requires a somewhat specific value.

If __len__ is set to return float("inf") or decimal.Decimal("Infinity"), len() rejects it by raising a TypeError. It also rejects the value of "-1" which would imply that the sequence is infinite. Furthermore, when I tried using an infinity class that I happen to have written earlier that does in fact inherit from int, len() for whatever reason returned 0.

While it isn't really a major inconvenience to allow the value to just be "0", and while a class like this is very unusual, I am still curious to know, is there a good way to handle the length attribute of a class that is an infinite sequence?

like image 316
trevorKirkby Avatar asked Dec 31 '15 02:12

trevorKirkby


4 Answers

__len__() must return a valid integer. Since you cannot, you should either not implement __len__(), if your sequences are always infinite, or raise a ValueError if you can sometimes give a meaningful length.

like image 75
SingleNegationElimination Avatar answered Sep 28 '22 08:09

SingleNegationElimination


I think the only reasonable solution is to not implement __len__ at all, since in fact your object does not have a length.

like image 30
David Zwicker Avatar answered Sep 28 '22 08:09

David Zwicker


Don't define __len__ for this class because that's semantically impossible to answer for it.

like image 41
Kirk Strauser Avatar answered Sep 28 '22 08:09

Kirk Strauser


As noted and in the documentation __len__ must return an integer >= 0, hence the TypeError.

Follow the example set by the infinite itertools.cycle and raise an appropriate TypeError to signify no length:

from itertools import cycle
c = cycle("a")
len(c)

TypeError: object of type 'itertools.cycle' has no len()
like image 20
Dimitris Fasarakis Hilliard Avatar answered Sep 28 '22 07:09

Dimitris Fasarakis Hilliard