产生一个recursion函数

我正在尝试对给定path下的所有文件进行操作。 我不想事先收集所有的文件名,然后用它们做一些事情,所以我试着这样做:

import os import stat def explore(p): s = '' list = os.listdir(p) for a in list: path = p + '/' + a stat_info = os.lstat(path ) if stat.S_ISDIR(stat_info.st_mode): explore(path) else: yield path if __name__ == "__main__": for x in explore('.'): print '-->', x 

但是这个代码跳过目录时,而不是让他们的内容。 我究竟做错了什么?

使用os.walk而不是重新发明轮子。

特别是,按照库文档中的例子,这是一个未经尝试的尝试:

 import os from os.path import join def hellothere(somepath): for root, dirs, files in os.walk(somepath): for curfile in files: yield join(root, curfile) # call and get full list of results: allfiles = [ x for x in hellothere("...") ] # iterate over results lazily: for x in hellothere("..."): print x 

迭代器不像这样recursion地工作。 你必须重新产生每个结果,通过replace

 explore(path) 

有类似的东西

 for value in explore(path): yield value 

为了达到这个目的, Python 3.3增加了yield from X的语法yield from X ,就像PEP380中提出的那样。 有了它,你可以做到这一点:

 yield from explore(path) 

如果使用生成器作为协同程序 ,则此语法还支持使用generator.send()将值传递回recursion调用的生成器。 以上简单for循环不会。

问题是这行代码:

 explore(path) 

它有什么作用?

  • 呼吁explore新的path
  • explore运行,创造一个发电机
  • 发电机返回explore(path)执行的地点
  • 并被丢弃

为什么被丢弃? 它没有分配任何东西,它没有被迭代 – 它完全被忽略。

如果你想对结果做些什么,那么你必须对它们做些什么! ;)

解决你的代码最简单的方法是:

 for name in explore(path): yield name 

当你确信自己明白发生了什么,你可能会想使用os.walk()来代替。

一旦你迁移到了Python 3.3(假设所有的工作都按计划进行),你将能够使用语法中的新的yield from在这一点上修复你的代码的最简单的方法是:

 yield from explore(path) 

改变这个:

 explore(path) 

对此:

 for subpath in explore(path): yield subpath 

或者使用os.walk ,因为phoojibuild议(这是更好的select)。

这就是所谓的functionexplore 。 你应该做的是迭代它像一个生成器:

 if stat.S_ISDIR(stat_info.st_mode): for p in explore(path): yield p else: yield path 

编辑:而不是stat模块,你可以使用os.path.isdir(path)

尝试这个:

 if stat.S_ISDIR(stat_info.st_mode): for p in explore(path): yield p 

如果你需要遍历所有的文件夹和子文件夹,os.walk是非常好的。 如果你不需要那就像用大象枪杀一只苍蝇。

但是,对于这个特定的情况,os.walk可能是一个更好的方法。

您也可以使用堆栈实现recursion。

这样做虽然没有任何优势,但是这是可能的。 如果您首先使用python,则性能提升可能不值得。

 import os import stat def explore(p): ''' perform a depth first search and yield the path elements in dfs order -implement the recursion using a stack because a python can't yield within a nested function call ''' list_t=type(list()) st=[[p,0]] while len(st)>0: x=st[-1][0] print x i=st[-1][1] if type(x)==list_t: if i>=len(x): st.pop(-1) else: st[-1][1]+=1 st.append([x[i],0]) else: st.pop(-1) stat_info = os.lstat(x) if stat.S_ISDIR(stat_info.st_mode): st.append([['%s/%s'%(x,a) for a in os.listdir(x)],0]) else: yield x print list(explore('.'))