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