29 Jun
2017
29 Jun
'17
11:09 p.m.
2017-06-25 Serhiy Storchakadixit: > 25.06.17 15:06, lucas via Python-ideas пише: > > I often use generators, and itertools.chain on them. > > What about providing something like the following: > > > > a = (n for n in range(2)) > > b = (n for n in range(2, 4)) > > tuple(a + b) # -> 0 1 2 3 [...] > It would be weird if the addition is only supported for instances of > the generator class, but not for other iterators. Why (n for n in > range(2)) > + (n for n in range(2, 4)) works, but iter(range(2)) + iter(range(2, > 4)) and iter([0, 1]) + iter((2, 3)) don't? itertools.chain() supports > arbitrary iterators. Therefore you will need to implement the __add__ > method for *all* iterators in the world. > > However itertools.chain() accepts not just *iterators*. [...] But implementation of the OP's proposal does not need to be based on __add__ at all. It could be based on extending the current behaviour of the `+` operator itself. Now this behavior is (roughly): try left side's __add__, if failed try right side's __radd__, if failed raise TypeError. New behavior could be (again: roughly): try left side's __add__, if failed try right side's __radd__, if failed try __iter__ of both sides and chain them (creating a new iterator¹), if failed raise TypeError. And similarly, for `+=`: try __iadd__..., try __add__..., try __iter__..., raise TypeError. Cheers. *j ¹ Preferably using the existing `yield from` mechanism -- because, in case of generators, it would provide a way to combine ("concatenate") *generators*, preserving semantics of all that their __next__(), send(), throw() nice stuff...