yield from () Was: Re: weirdness with list()

Chris Angelico rosuav at gmail.com
Thu Mar 11 16:30:30 EST 2021


On Fri, Mar 12, 2021 at 8:20 AM Serhiy Storchaka <storchaka at gmail.com> wrote:
>
> 01.03.21 23:59, Cameron Simpson пише:
> > On 28Feb2021 23:47, Alan Gauld <alan.gauld at yahoo.co.uk> wrote:
> >> On 28/02/2021 00:17, Cameron Simpson wrote:
> >>> BUT... It also has a __iter__ value, which like any Box iterates over
> >>> the subboxes. For MDAT that is implemented like this:
> >>>
> >>>     def __iter__(self):
> >>>         yield from ()
> >>
> >> Sorry, a bit OT but I'm curious. I haven't seen
> >> this before:
> >>
> >> yield from ()
> >>
> >> What is it doing?
> >> What do the () represent in this context?
> >
> > It's an empty tuple. The yield from iterates over the tuple, yielding
> > zero times. There are shorter ways to write that (eg outright omitting
> > the yield), except when you're writing a generator function with only a
> > single yield statement - then you need something like that to make it a
> > generator.
>
> I was wondering what from following variants is more efficient:
>
>     def gen1():
>         yield from ()
>
>     def gen2():
>         return
>         yield
>
>     def gen3():
>         return iter(())
>
>
> $ python3.9 -m timeit -s 'def g(): yield from ()' 'list(g())'
> 1000000 loops, best of 5: 266 nsec per loop
> $ python3.9 -m timeit -s 'def g():' -s ' return' -s ' yield' 'list(g())'
> 1000000 loops, best of 5: 219 nsec per loop
> $ python3.9 -m timeit -s 'def g(): return iter(())' 'list(g())'
> 2000000 loops, best of 5: 192 nsec per loop
>

They're not identical. The first two are, I believe, equivalent (and
you could add "if False: yield" as another comparison if you care),
but the third one isn't a generator. So if all you need is an
iterator, sure, but gen3 actually isn't doing as much as the other two
are.

ChrisA


More information about the Python-list mailing list