Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #31866 > unrolled thread

Recursive Generator Error?

Started byDavid <zhushenli@gmail.com>
First post2012-10-21 16:29 -0700
Last post2012-10-22 02:36 +0000
Articles 5 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Recursive Generator Error? David <zhushenli@gmail.com> - 2012-10-21 16:29 -0700
    Re: Recursive Generator Error? Terry Reedy <tjreedy@udel.edu> - 2012-10-21 19:59 -0400
      Re: Recursive Generator Error? David <zhushenli@gmail.com> - 2012-10-21 17:40 -0700
      Re: Recursive Generator Error? David <zhushenli@gmail.com> - 2012-10-21 17:40 -0700
        Re: Recursive Generator Error? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-10-22 02:36 +0000

#31866 — Recursive Generator Error?

FromDavid <zhushenli@gmail.com>
Date2012-10-21 16:29 -0700
SubjectRecursive Generator Error?
Message-ID<d1dbc8a7-1ec6-474c-96d7-b95a066125dd@googlegroups.com>
I have a tree-like data structure, the basic elements are hash tables,
and they are grouped into lists, like [[{'a':1},[{'b':2}]]].
And I want to flat the lists and visit hash table one by one, like {'a':1}, {'b':2}.
But my program didn't work as I wish. When it entered the 2nd
flat_yield, it threw a GeneratorExit. Is there anything wrong?
Thank you very much!

#- - - - - - - - - - 
def flat_yield(tbl_list):
    for t in tbl_list:
        if type(t) == type({}):
            yield t
        elif type(t) == type([]):
            flat_yield(t)
a = [[{'a':1},[{'b':2}]]]
for i in flat_yield(a):
    print i

[toc] | [next] | [standalone]


#31867

FromTerry Reedy <tjreedy@udel.edu>
Date2012-10-21 19:59 -0400
Message-ID<mailman.2608.1350863992.27098.python-list@python.org>
In reply to#31866
On 10/21/2012 7:29 PM, David wrote:
> I have a tree-like data structure, the basic elements are hash tables,
> and they are grouped into lists, like [[{'a':1},[{'b':2}]]].
> And I want to flat the lists and visit hash table one by one, like {'a':1}, {'b':2}.
> But my program didn't work as I wish. When it entered the 2nd
> flat_yield, it threw a GeneratorExit. Is there anything wrong?

1. The Python version is not specified.
2. You used 2.x; in 3.3 the code does exactly what I would expect, which 
is to say, nothing. No output, no error, no traceback ;-)
3. The traceback is missing from this post.

> #- - - - - - - - - -
> def flat_yield(tbl_list):
>      for t in tbl_list:
>          if type(t) == type({}):
>              yield t
>          elif type(t) == type([]):
>              flat_yield(t)

4. Think harder about what that expression does.

> a = [[{'a':1},[{'b':2}]]]
> for i in flat_yield(a):
>      print i

Hint: it calls flat_yield, which returns a generator, which is then 
discarded. You might have well written 'pass'.

Solution: use the recursively called generator and recursively yield 
what it yields. Replace 'flat_yield(t)' with

             for item in flat_yield(t):
                 yield item

and the output is what you want.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#31871

FromDavid <zhushenli@gmail.com>
Date2012-10-21 17:40 -0700
Message-ID<7f9d09d5-34a3-4d85-b996-b0023d46cfd8@googlegroups.com>
In reply to#31867
On Monday, October 22, 2012 7:59:53 AM UTC+8, Terry Reedy wrote:
> On 10/21/2012 7:29 PM, David wrote:
> 
> > I have a tree-like data structure, the basic elements are hash tables,
> 
> > and they are grouped into lists, like [[{'a':1},[{'b':2}]]].
> 
> > And I want to flat the lists and visit hash table one by one, like {'a':1}, {'b':2}.
> 
> > But my program didn't work as I wish. When it entered the 2nd
> 
> > flat_yield, it threw a GeneratorExit. Is there anything wrong?
> 
> 
> 
> 1. The Python version is not specified.
> 
> 2. You used 2.x; in 3.3 the code does exactly what I would expect, which 
> 
> is to say, nothing. No output, no error, no traceback ;-)
> 
> 3. The traceback is missing from this post.
> 
> 
> 
> > #- - - - - - - - - -
> 
> > def flat_yield(tbl_list):
> 
> >      for t in tbl_list:
> 
> >          if type(t) == type({}):
> 
> >              yield t
> 
> >          elif type(t) == type([]):
> 
> >              flat_yield(t)
> 
> 
> 
> 4. Think harder about what that expression does.
> 
> 
> 
> > a = [[{'a':1},[{'b':2}]]]
> 
> > for i in flat_yield(a):
> 
> >      print i
> 
> 
> 
> Hint: it calls flat_yield, which returns a generator, which is then 
> 
> discarded. You might have well written 'pass'.
> 
> 
> 
> Solution: use the recursively called generator and recursively yield 
> 
> what it yields. Replace 'flat_yield(t)' with
> 
> 
> 
>              for item in flat_yield(t):
> 
>                  yield item
> 
> 
> 
> and the output is what you want.
> 
> 
> 
> -- 
> 
> Terry Jan Reedy

Hi Terry, thank you! I use Python 2.7, and your solution works!

I have thought harder, still not very clear. 

If I have one "yield" in function, the function will become generator, and it can only be called in the form like "for item in function()" or "function.next()", and call the function directly will raise error, is it right?

[toc] | [prev] | [next] | [standalone]


#31872

FromDavid <zhushenli@gmail.com>
Date2012-10-21 17:40 -0700
Message-ID<mailman.2614.1350866449.27098.python-list@python.org>
In reply to#31867
On Monday, October 22, 2012 7:59:53 AM UTC+8, Terry Reedy wrote:
> On 10/21/2012 7:29 PM, David wrote:
> 
> > I have a tree-like data structure, the basic elements are hash tables,
> 
> > and they are grouped into lists, like [[{'a':1},[{'b':2}]]].
> 
> > And I want to flat the lists and visit hash table one by one, like {'a':1}, {'b':2}.
> 
> > But my program didn't work as I wish. When it entered the 2nd
> 
> > flat_yield, it threw a GeneratorExit. Is there anything wrong?
> 
> 
> 
> 1. The Python version is not specified.
> 
> 2. You used 2.x; in 3.3 the code does exactly what I would expect, which 
> 
> is to say, nothing. No output, no error, no traceback ;-)
> 
> 3. The traceback is missing from this post.
> 
> 
> 
> > #- - - - - - - - - -
> 
> > def flat_yield(tbl_list):
> 
> >      for t in tbl_list:
> 
> >          if type(t) == type({}):
> 
> >              yield t
> 
> >          elif type(t) == type([]):
> 
> >              flat_yield(t)
> 
> 
> 
> 4. Think harder about what that expression does.
> 
> 
> 
> > a = [[{'a':1},[{'b':2}]]]
> 
> > for i in flat_yield(a):
> 
> >      print i
> 
> 
> 
> Hint: it calls flat_yield, which returns a generator, which is then 
> 
> discarded. You might have well written 'pass'.
> 
> 
> 
> Solution: use the recursively called generator and recursively yield 
> 
> what it yields. Replace 'flat_yield(t)' with
> 
> 
> 
>              for item in flat_yield(t):
> 
>                  yield item
> 
> 
> 
> and the output is what you want.
> 
> 
> 
> -- 
> 
> Terry Jan Reedy

Hi Terry, thank you! I use Python 2.7, and your solution works!

I have thought harder, still not very clear. 

If I have one "yield" in function, the function will become generator, and it can only be called in the form like "for item in function()" or "function.next()", and call the function directly will raise error, is it right?

[toc] | [prev] | [next] | [standalone]


#31874

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-10-22 02:36 +0000
Message-ID<5084b11e$0$11126$c3e8da3@news.astraweb.com>
In reply to#31872
On Sun, 21 Oct 2012 17:40:41 -0700, David wrote:

> If I have one "yield" in function, the function will become generator,

Almost correct. The function becomes a *generator function*, that is, a 
function that returns a generator object.

Sometimes people abbreviate that to "generator", but that is ambiguous -- 
the term "generator" can mean either the function which includes yield in 
it, or the object that is returned.

> and it can only be called in the form like "for item in function()" or
> "function.next()", and call the function directly will raise error, is
> it right?

You can call the function directly, and it will return an generator 
object. You don't have to iterate over that generator object, although 
you normally will.

Example:

py> def test():
...     yield 42
... 
py> test
<function test at 0xb7425764>
py> type(test)
<type 'function'>
py> x = test()
py> x
<generator object test at 0xb71d4874>
py> type(x)
<type 'generator'>


-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web