Confusing listreverseiterator Behavior

Hi, I stumbled upon a confusing listreverseiterator behavior:
This is the only reverse iterator with that sort of behavior. Is that intentional if yes, why? I stumbled upon that when writing a templating engine that tried to lazily get the length of the sequence / iterator but failed doing so after the first iteration because the length of the reverse iterator changes every iteration. Regards, Armin

Unless I'm misconstruing something the problem is that reversed returns two different object types depending on if it's a list or a tuple
reversing a tuple (or a string) returns a "reversed object" reversing a list returns a "listreverseiterator" definitely an inconsistency

I realized after I fired off my response that this was still bugging me... it appears that the documentation is incorrect from 2.1 Built-in Functions (v2.5 in case it matters... a quick search of bugs doesn't seem to show anything though) *reversed*( seq) Return a reverse iterator. seq must be an object which supports the sequence protocol (the __len__() method and the __getitem__()method with integer arguments starting at 0). New in version 2.4. the above appears to only be true for lists. For tuples and strings it creates a reverse OBJECT which behaves slightly differently (notably by not including a len() method as you noticed) I can't find how to actually create a "tuplereverseiterator" or "stringreverseiterator" objects... nor does there appear to be a way to create a "reversed" object from a list... Just tested this s = 'bob' t = (1,2,3,4) l = [1,2,3,4) rs = reversed(s) rt = reversed(t) rl = reversed(l) type(rs) <type 'reversed'> type(rt) <type 'reversed'> type(rl) <type 'listreverseiterator'> type(rs) == type(rt) True type(rs) == type(rl) False Surely this isn't intentional? -------- Haikus are easy Most make very little sense Refrigerator

Jeff Hall <hall.jeff <at> gmail.com> writes:
The problem I personally have with it is that the listreverseiterator is the only iterator in the standard library that changes the length during iteration and that it's the only reverse iterator that has a length. Even more stunning as the normal iterator doesn't have one. Regards, Armin

Jeff Hall schrieb:
Not at all. (I think you misread; the __len__ method must be present on the argument, not the returned object.)
You don't need to. An object returned by reversed() only needs to follow the iterator protocol. Whether it is a listreverseiterator or a general reversed object doesn't matter. In fact, reversed() calls __reversed__ on its argument if it exists, so that custom types may provide their own optimized reverse iterator. Georg

From: "Armin Ronacher" <armin.ronacher@active-4.com>
Use the bug tracker please and assign to me. At one time, some iterators had the ability to know their own length and that would change as the iterator got consumed. Later, it was decided that iterators should not report length and should instead report a length hint. It looks like listreversediterator got missed when this was changed. Raymond

Unless I'm misconstruing something the problem is that reversed returns two different object types depending on if it's a list or a tuple
reversing a tuple (or a string) returns a "reversed object" reversing a list returns a "listreverseiterator" definitely an inconsistency

I realized after I fired off my response that this was still bugging me... it appears that the documentation is incorrect from 2.1 Built-in Functions (v2.5 in case it matters... a quick search of bugs doesn't seem to show anything though) *reversed*( seq) Return a reverse iterator. seq must be an object which supports the sequence protocol (the __len__() method and the __getitem__()method with integer arguments starting at 0). New in version 2.4. the above appears to only be true for lists. For tuples and strings it creates a reverse OBJECT which behaves slightly differently (notably by not including a len() method as you noticed) I can't find how to actually create a "tuplereverseiterator" or "stringreverseiterator" objects... nor does there appear to be a way to create a "reversed" object from a list... Just tested this s = 'bob' t = (1,2,3,4) l = [1,2,3,4) rs = reversed(s) rt = reversed(t) rl = reversed(l) type(rs) <type 'reversed'> type(rt) <type 'reversed'> type(rl) <type 'listreverseiterator'> type(rs) == type(rt) True type(rs) == type(rl) False Surely this isn't intentional? -------- Haikus are easy Most make very little sense Refrigerator

Jeff Hall <hall.jeff <at> gmail.com> writes:
The problem I personally have with it is that the listreverseiterator is the only iterator in the standard library that changes the length during iteration and that it's the only reverse iterator that has a length. Even more stunning as the normal iterator doesn't have one. Regards, Armin

Jeff Hall schrieb:
Not at all. (I think you misread; the __len__ method must be present on the argument, not the returned object.)
You don't need to. An object returned by reversed() only needs to follow the iterator protocol. Whether it is a listreverseiterator or a general reversed object doesn't matter. In fact, reversed() calls __reversed__ on its argument if it exists, so that custom types may provide their own optimized reverse iterator. Georg

From: "Armin Ronacher" <armin.ronacher@active-4.com>
Use the bug tracker please and assign to me. At one time, some iterators had the ability to know their own length and that would change as the iterator got consumed. Later, it was decided that iterators should not report length and should instead report a length hint. It looks like listreversediterator got missed when this was changed. Raymond
participants (4)
-
Armin Ronacher
-
Georg Brandl
-
Jeff Hall
-
Raymond Hettinger