[Python-ideas] Re: execute function on iterator items without changing or consuming iterator

2020-10-25 Thread Joao S. O. Bueno
this seems nice.

It just seems that the obvious way to do it would be:

def tap(iter_, func):
   for item in iter_:
   func(item)
   yield item



I think it can be nice, but more as cookbook material than an actual
itertools function.



On Sun, 25 Oct 2020 at 14:38, <2qdxy4rzwzuui...@potatochowder.com> wrote:

> On 2020-10-25 at 16:34:14 +,
> George Harding  wrote:
>
> > some_iter = map(lambda x: x if print(x) else x, some_iter)
> >
> > The tuple has a ~50% overhead, the case statement ~15%, compared to the
> > generator.
>
> def print_first(x):
> print(x)
> return x
> new_iter = map(print_first, some_iter)
>
> No extranous tuple, no extranous case stament.  Newlines are cheap these
> days.  The call to print, however, is possibly unbounded in time and
> space.
>
> If you really want to go overboard, put something like the following
> peeker function into your personal toolbox (untested):
>
> def peeker(function):
> def peeker(x):
> function(x)
> return x
> return peeker
>
> And use it like this:
>
> new_iter = map(peeker(print), some_iter)
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/RG2ZQD5NNU2BKVTC2AZGSQNVZA2CV2UJ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/RUNCSDTTB5NTGYUUQAFZZI33XBZSEWUZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: execute function on iterator items without changing or consuming iterator

2020-10-25 Thread 2QdxY4RzWzUUiLuE
On 2020-10-25 at 16:34:14 +,
George Harding  wrote:

> some_iter = map(lambda x: x if print(x) else x, some_iter)
> 
> The tuple has a ~50% overhead, the case statement ~15%, compared to the
> generator.

def print_first(x):
print(x)
return x
new_iter = map(print_first, some_iter)

No extranous tuple, no extranous case stament.  Newlines are cheap these
days.  The call to print, however, is possibly unbounded in time and
space.

If you really want to go overboard, put something like the following
peeker function into your personal toolbox (untested):

def peeker(function):
def peeker(x):
function(x)
return x
return peeker

And use it like this:

new_iter = map(peeker(print), some_iter)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/RG2ZQD5NNU2BKVTC2AZGSQNVZA2CV2UJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: execute function on iterator items without changing or consuming iterator

2020-10-25 Thread George Harding
less awkward is:

some_iter = map(lambda x: x if print(x) else x, some_iter)

The tuple has a ~50% overhead, the case statement ~15%, compared to the
generator.

I think that the less awkward syntax solves the problem fine (if you can
come up with it). I like that it's explicit rather than requiring someone
to know what itertools.tap does.

On Sun, Oct 25, 2020 at 4:27 PM Samuel Freilich via Python-ideas <
python-ideas@python.org> wrote:

> This seems like it might be a reasonable thing to have in intertools? It's
> not hard to write this sort of thing with map:
>
> some_iter = map(lambda x: (print(x), x)[1], some_iter)
>
> But it's a little awkward. (Though maybe I'm missing a less awkward way to
> do that.)
>
> Java has Stream.peek for similar functionality, while Stream.forEach is
> analogous to Python's map.
>
> On Sun, Oct 25, 2020 at 9:02 AM  wrote:
>
>> Python has many tools for iteration, such as map and filter, that change
>> an iterator into another iterator without consuming the iterator. These
>> make it simple to deal with many items in a list without consuming
>> excessive memory.
>>
>> Occasionally it is useful to be able to tap into iterator items and
>> execute a function (such as a side effect to validate elements or print
>> them) without making any changes to the overall iterator. This is similar
>> to the idea of a tap in rxjs:
>> https://rxjs-dev.firebaseapp.com/api/operators/tap.
>>
>> The proposed interface would be:
>> def generate_items() -> list[int]:
>> some_iter = range(10)
>> some_iter = tap(assert_int, some_iter)
>> some_iter = tap(print, some_iter)
>> return list(some_iter)
>>
>> This would be useful to (for example):
>> 1. Debug chained iterators without a debugger (at the moment you would
>> have to convert the list and then print the whole list or include a print
>> statement in one of the chained functions)
>> 2. Check that items in an iterator conform to assumptions and raising
>> exceptions if they do not
>> 3. Improve type hints in editors since after the assert is executed all
>> items conform to the assert in the tap (for example, they are an integer)
>>
>> The implementation would be quite simple (at least in python):
>> def tap(func: typing.Callable[[T], typing.Any], iter: typing.Iterable[T])
>> -> typing.iterable[T]:
>> for item in iter:
>> func(item)
>> yield item
>>
>> Thoughts?
>> ___
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/7Q3NR4SKUC72PVQ3APK2HL2HNX3HP2IE/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/7AUUGTM77ZJFJ4PSZUYHB2PW2VJKBYYT/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XJQMJU3PJ3AWOTB5MTGNHLNVAVIZG7K6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: execute function on iterator items without changing or consuming iterator

2020-10-25 Thread Samuel Freilich via Python-ideas
This seems like it might be a reasonable thing to have in intertools? It's
not hard to write this sort of thing with map:

some_iter = map(lambda x: (print(x), x)[1], some_iter)

But it's a little awkward. (Though maybe I'm missing a less awkward way to
do that.)

Java has Stream.peek for similar functionality, while Stream.forEach is
analogous to Python's map.

On Sun, Oct 25, 2020 at 9:02 AM  wrote:

> Python has many tools for iteration, such as map and filter, that change
> an iterator into another iterator without consuming the iterator. These
> make it simple to deal with many items in a list without consuming
> excessive memory.
>
> Occasionally it is useful to be able to tap into iterator items and
> execute a function (such as a side effect to validate elements or print
> them) without making any changes to the overall iterator. This is similar
> to the idea of a tap in rxjs:
> https://rxjs-dev.firebaseapp.com/api/operators/tap.
>
> The proposed interface would be:
> def generate_items() -> list[int]:
> some_iter = range(10)
> some_iter = tap(assert_int, some_iter)
> some_iter = tap(print, some_iter)
> return list(some_iter)
>
> This would be useful to (for example):
> 1. Debug chained iterators without a debugger (at the moment you would
> have to convert the list and then print the whole list or include a print
> statement in one of the chained functions)
> 2. Check that items in an iterator conform to assumptions and raising
> exceptions if they do not
> 3. Improve type hints in editors since after the assert is executed all
> items conform to the assert in the tap (for example, they are an integer)
>
> The implementation would be quite simple (at least in python):
> def tap(func: typing.Callable[[T], typing.Any], iter: typing.Iterable[T])
> -> typing.iterable[T]:
> for item in iter:
> func(item)
> yield item
>
> Thoughts?
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/7Q3NR4SKUC72PVQ3APK2HL2HNX3HP2IE/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7AUUGTM77ZJFJ4PSZUYHB2PW2VJKBYYT/
Code of Conduct: http://python.org/psf/codeofconduct/