Ali*_*Ali 52 python recursion iterator yield directory-structure
我正在尝试对给定路径下的所有文件执行某些操作.我不想事先收集所有的文件名然后用它们做一些事情,所以我尝试了这个:
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
Run Code Online (Sandbox Code Playgroud)
但是这个代码在命中它们时会跳过目录,而不是让它们产生内容.我究竟做错了什么?
小智 126
迭代器不会像那样递归地工作.您必须通过替换重新产生每个结果
explore(path)
Run Code Online (Sandbox Code Playgroud)
喜欢的东西
for value in explore(path):
yield value
Run Code Online (Sandbox Code Playgroud)
Python 3.3添加了PEP 380中yield from X
提出的语法来实现此目的.有了它,你可以这样做:
yield from explore(path)
Run Code Online (Sandbox Code Playgroud)
如果您使用生成器作为协同程序,则此语法还支持使用generator.send()
将值传递回递归调用的生成器.for
上面的简单循环不会.
Eth*_*man 36
问题是这行代码:
explore(path)
Run Code Online (Sandbox Code Playgroud)
它有什么作用?
explore
用新电话打电话path
explore
运行,创建一个发电机explore(path)
执行的位置...它为什么被丢弃?它没有分配给任何东西,它没有被迭代 - 它被完全忽略了.
如果你想对结果做点什么,那么你必须对它们做点什么!;)
修复代码的最简单方法是:
for name in explore(path):
yield name
Run Code Online (Sandbox Code Playgroud)
如果您确信自己了解正在发生的事情,那么您可能希望使用它os.walk()
.
一旦迁移到Python 3.3(假设所有工作都按计划完成),您将能够使用新yield from
语法,最简单的方法是在此时修复代码:
yield from explore(path)
Run Code Online (Sandbox Code Playgroud)
pho*_*oji 25
使用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
Run Code Online (Sandbox Code Playgroud)
改变这个:
explore(path)
Run Code Online (Sandbox Code Playgroud)
对此:
for subpath in explore(path):
yield subpath
Run Code Online (Sandbox Code Playgroud)
或者os.walk
像phooji建议的那样使用(这是更好的选择).