<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>On Jan 3, 2015, at 16:53, yotam vaknin <<a href="mailto:tomirendo@gmail.com">tomirendo@gmail.com</a>> wrote:</div><div><br></div><blockquote type="cite"><div><div dir="rtl"><div dir="ltr">Sorry, I probably wasn't clear enough.</div><div dir="ltr">My idea was to add these method (__add__, __getitem__) to the already available iterators (map,zip,dict.items) and generators by default. Not to make these methods part of the iterator protocol.</div></div></div></blockquote><div><br></div>Well, dict.items doesn't return an iterator, it returns an iterable view.<div><br></div><div>More importantly, if you add this just to generators and map and zip, it won't apply to (among other things) filter; the built-in iterators for list, tuple, set, dict, and the dict views; the special type used to iterate types that implement __getitem__ but not __iter__; any of the iterators from itertools--including the result of slicing or chaining two map iterators; files; csv readers; XML iterparse; …</div><div><br></div><div>I think that would make the language a lot worse. In general, code doesn't care whether it's gotten an iterator from mapping a function over a file, chaining two iterators together, or iterating a sequence. If you wrote some code that expected to get a generator, used the + operator, and then changed the calling code to filter that generator, it would break, for no good reason.</div><div><br></div><div>If you really wanted to, you could make this general pretty easily: change the meaning of the + operator so that, after checking __add__ and __radd__, before raising a TypeError, it checks whether both operand have __iter__ methods and, if so, it returns a chain of the two.</div><div><div><br></div><div>Slicing has another problem, however. First, it's a bit odd to be able to do i[5:7] but not i[5]. But, more seriously, I wouldn't expect i[5:7] to give me an iterable that, when accessed, discards the first 5 elements of i. And imagine how confusing this code would be:</div><div><br></div><div>    >>> i = iter(range(10))</div><div>    >>> a = i[2:4]</div><div>    >>> b = i[4:6]</div><div>    >>> list(a)</div><div>    [2, 3]</div><div>    >>> list(b)</div><div>    [8, 9]</div><div><br></div><div>Hiding the fact that i is an iterable rather than a sequence will just confuse your readers.</div><br><blockquote type="cite"><div><div class="gmail_extra"><div class="gmail_quote"><div dir="ltr">2015-01-03 17:28 GMT+02:00 Steven D'Aprano <span dir="ltr"><<a href="mailto:steve@pearwood.info" target="_blank">steve@pearwood.info</a>></span>:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Sat, Jan 03, 2015 at 03:37:03PM +0200, yotam vaknin wrote:<br>
> I would like to purpose that in python 3 it will be easy to chain and slice<br>
> Iterators just like you can add and slice lists and tuples easily.<br>
><br>
> I think there could be 2 methods to do this:<br>
> 1. Implementing '+' and slicing ([1:2:3]) for iterators and generators by<br>
> default, Resulting in  Itertool's chain(a,b) and islice(a,b,c) respectively.<br>
> 2. Having itertool's chain and islice imported by default.<br>
<br>
</span>The iterator protocol is intentionally simple. To create an iterator,<br>
you need to only define two methods:<br>
<br>
(1) __iter__, which returns the instance itself;<br>
<br>
(2) __next__, which returns the next item and raises StopIterator when<br>
done.<br>
<br>
<br>
With your proposal, you would have to define two or three more methods:<br>
<br>
(3) __add__ and possibly __radd__, to chain iterators;<br>
<br>
(4) __getitem__, for slicing.<br>
<br>
There is nothing stopping you from adding these methods to your own<br>
iterator classes, but with your proposal that would be compulsory for<br>
all iterators.<br>
<span class=""><br>
<br>
> I think since python 3 return zip,map, dict.items and so on as iterators,<br>
> it makes working with those kind of objects more difficult without having<br>
> these methods around. And since those methods are important enough to have<br>
> for lists, it seems important enough for iterators too.<br>
<br>
</span>It only takes a single line of code to get iterator chaining and<br>
slicing:<br>
<br>
from itertools import chain, islice<br>
<br>
And now you can chain and slice any iterator, regardless of where it<br>
came from. I don't think that is difficult.<br>
<br>
*If* iterators where instances of a concrete base class, then it would<br>
make sense to add chain and slice methods to that base class so all<br>
other iterators could inherit from it. But they aren't, iterators in<br>
Python are values which obey a protocol, not inheritence. That means<br>
that a functional approach, like itertools, is more appropriate.<br>
<br>
I can see the appeal of using + and [a:b:c] syntax instead of function<br>
syntax chain() and islice(), but I don't think the advantage is enough<br>
to out-weigh the costs.<br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
<br>
--<br>
Steve<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</font></span></blockquote></div><br></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Python-ideas mailing list</span><br><span><a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a></span><br><span><a href="https://mail.python.org/mailman/listinfo/python-ideas">https://mail.python.org/mailman/listinfo/python-ideas</a></span><br><span>Code of Conduct: <a href="http://python.org/psf/codeofconduct/">http://python.org/psf/codeofconduct/</a></span></div></blockquote></div></body></html>