On Thu, Mar 7, 2013 at 4:22 AM, Wolfgang Maier <wolfgang.ma...@biologie.uni-freiburg.de> wrote: > Well, it skips the costly len() call because your iter(Foo()) returns > iter(range()) under the hood and list() uses that object's __len__() method.
Iterators do not generally have __len__ methods. >>> len(iter(range(10))) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'range_iterator' has no len() > In > most cases, such a workaround will not be feasible. Why should > iter(QuerySet()) > have a faster __len__() method defined than QuerySet() itself. iter(QuerySet()) should not have any __len__ method defined at all, which is why the optimization would be skipped. > Most likely, > iter(QuerySet()) just returns self anyway? But on this point, you are correct. The mongoengine QuerySet.__iter__ method is defined as: def __iter__(self): self.rewind() return self This is unfortunate design. Not only does it mean that the iterator's __len__ method cannot be trusted (what should the __len__ of a partially exhausted iterator return?), but it also means that requesting an iterator over the QuerySet will also silently invalidate any existing iterators. -- http://mail.python.org/mailman/listinfo/python-list