Recursive Generator Error?

Discussion in 'Python' started by David, Oct 22, 2012.

  1. David

    David Guest

    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
     
    David, Oct 22, 2012
    #1
    1. Advertising

  2. David

    Terry Reedy Guest

    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
     
    Terry Reedy, Oct 22, 2012
    #2
    1. Advertising

  3. David

    David Guest

    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?
     
    David, Oct 22, 2012
    #3
  4. David

    David Guest

    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?
     
    David, Oct 22, 2012
    #4
  5. 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
     
    Steven D'Aprano, Oct 22, 2012
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. MetalOne
    Replies:
    11
    Views:
    502
    Andrew Koenig
    Dec 21, 2003
  2. Paul Chiusano

    Recursive Generator Question

    Paul Chiusano, Sep 3, 2004, in forum: Python
    Replies:
    8
    Views:
    425
    Brian McErlean
    Sep 3, 2004
  3. aurora
    Replies:
    7
    Views:
    325
    Steven Bethard
    Aug 12, 2005
  4. n00m
    Replies:
    12
    Views:
    1,119
  5. vamsi
    Replies:
    21
    Views:
    2,089
    Keith Thompson
    Mar 9, 2009
Loading...

Share This Page