##language:zh #pragma section-numbers off ##含有章节索引导航的 ZPyUG 文章通用模板 <> ## 默许导航,请保留 <> = yeild 的递归输出问题 = {{{ Zoom.Quiet zoom.quiet@gmail.com 发件人当地时间 发送时间 17:57 (GMT+08:00)。发送地当前时间:下午8:05。 ✆ 日期 2011年8月25日 下午5:57 主题 yeild 的递归输出问题 }}} ##startInc == 问题 == 背景:: - 要对一堆有相同结构,但是有不定深度的嵌套数据进行输出整理 e.g: 类似数据对象 {{{ #!python DATA= { 'SEQ':{ "id1":['id11', 'id12'] ,"id11":['id111'] ,"id111":['id1111'] ,"id12":['id21'] ,"id21":['id211', 'id212'] } ,'DESC':{'id1':{'title':1,'type':'folder'} ,'id11':{'title':11,'type':'folder'} ,'id12':{'title':12,'type':'file'} ,'id111':{'title':111,'type':'file'} ,'id1111':{'title':1111,'type':'file'} ,'id21':{'title':21,'type':'folder'} ,'id211':{'title':211,'type':'file'} ,'id212':{'title':212,'type':'file'} } } }}} * SEQ 中包含了各种子节点的关系;不在其中keys() 的都是内容节点; * DESC 中包含了所有节点的内容描述; 当前:: {{{ #!python import types def _exp_all_item(drdf, seq, exp): if types.ListType is type(seq): for seqid in seq: if seqid in drdf['SEQ']: print "
  • %s" % drdf['DESC'][seqid]['title'] _exp_all_item(drdf,drdf['SEQ'][seqid],exp) else: _exp_all_item(drdf,seqid,exp) else: if seq in drdf['SEQ']: print "
  • %s" % drdf['DESC'][seq]['title'] _exp_all_item(drdf,drdf['SEQ'][seq],exp) else: print "
  • %s
  • " % drdf['DESC'][seq]['title'] if __name__ == "__main__": htm = "" _exp_all_item(DATA, 'id1', htm) }}} 可以很好的输出所有层次的数据: {{{
  • 1
  • 11
  • 111
  • 1111
  • 12
  • 21
  • 211
  • 212
  • }}} 但是!如果数据非常大,立即就有: ``RuntimeError: maximum recursion depth exceeded in cmp`` 目标: 使用 yield 可以进行方便的生成器,迭代化: {{{ #!python def _exp_all_item(drdf, seq, exp): if types.ListType is type(seq): for seqid in seq: if seqid in drdf['SEQ']: print "
  • %s" % drdf['DESC'][seqid]['title'] yield _exp_all_item(drdf,drdf['SEQ'][seqid],exp) else: yield _exp_all_item(drdf,seqid,exp) else: if seq in drdf['SEQ']: print "
  • %s" % drdf['DESC'][seq]['title'] yield _exp_all_item(drdf,drdf['SEQ'][seq],exp) else: print "
  • %s
  • " % drdf['DESC'][seq]['title'] }}} 问题! * yield 后,立即惰性化,不能自主完成挖掘输出 * {{{ 直接 print ,都是生成器对象了: 问题是期望函式可以自动完成挖掘,在 yield 后如何激活? - 网络中的实例,和图书中也都说 yield 应该配合列表什么的进行 .next() 步进 - 没有其它方便的自动完成形式? }}} * 另外,发现,不论硬递归,还是 yield ,都无法简单的将数据输出到函式外部 比如说: {{{ #!python def _exp_all_item(drdf, seq, exp): if types.ListType is type(seq): for seqid in seq: if seqid in drdf['SEQ']: exp+= "
  • %s" % drdf['DESC'][seqid]['title'] _exp_all_item(drdf,drdf['SEQ'][seqid],exp) else: _exp_all_item(drdf,seqid,exp) else: if seq in drdf['SEQ']: exp+= "
  • %s" % drdf['DESC'][seq]['title'] _exp_all_item(drdf,drdf['SEQ'][seq],exp) else: exp+= "
  • %s
  • " % drdf['DESC'][seq]['title'] return exp }}} 这样,并不能完成所有数据的统一收集,只能输出最后的一次迭代,,, 这事儿,怎么想呢? == Limodou == {{{ limodou limodou@gmail.com 发件人当地时间 发送时间 19:49 (GMT+08:00)。发送地当前时间:下午8:07。 ✆ }}} 我理解你是想将所有数据放到一个变量中,代码如下: {{{ #!python def _exp_all_item(drdf, seq, exp): if types.ListType is type(seq): for seqid in seq: if seqid in drdf['SEQ']: yield "
  • %s" % drdf['DESC'][seqid]['title'] for x in _exp_all_item(drdf,drdf['SEQ'][seqid],exp): yield x else: for x in _exp_all_item(drdf,seqid,exp): yield x else: if seq in drdf['SEQ']: yield "
  • %s" % drdf['DESC'][seq]['title'] for x in _exp_all_item(drdf,drdf['SEQ'][seq],exp): yield x else: yield "
  • %s
  • " % drdf['DESC'][seq]['title'] if __name__ == '__main__': s = list(_exp_all_item(DATA, 'id1', '')) print s }}} 上面的关键就是,在递归时,对于返回的结果要通过for将generator解开,再通过yield返回。而不是直接返回一个generator. {{{ $ python demoyield.py ['
  • 1' , '
  • 11' , '
  • 111' , '
  • 1111
  • ' , '
  • 12' , '
  • 21' , '
  • 211
  • ' , '
  • 212
  • ' ] }}} === 感触 === * 果然!一切返回处都要用 yield * 包含 yield 的函式,都要用 list 激发迭代! ``受教了!`` ##endInc ---- '''反馈''' 创建 by -- ZoomQuiet [<>]