如果嵌套递归 的迭代器,例如下面错误的代码
def iter_tar_file(self,file):
if not tarfile.is_tarfile(file):
raise ValueError("请传入有效的tar文件")
tar = tarfile.TarFile.open(file)
names = tar.getnames()
for filename in names:
if filename.endswith("tar") or filename.endswith("tar.gz"):
self.iter_tar_file(filename) # 递归返回
continue
bytes_count = tar.gettarinfo(filename).size
yield bytes_count
外面调用
for i in iter_tar_file:
print(i)
self.iter_tar_file(filename) # 递归返回
上面一行的数据是不会反回的。只会返回最外层的,因为哪一个递归函数,相当于没有接收对象,虽然有返回值,但是并没有传到外面。
错误的改进方法
yield self.iter_tar_file(filename) # 递归返回
这样做只是yield 一个迭代器对象,并没有把里面的值返回
迭代器吗,只能返回到调用他的那一层,并不会越级返回,
<generator object get_tar_size at 0x0000000004D5EB88>
image.png
对此有两个解决办法:
第一种就是用 for 把递归返回到外面
for i in self.iter_tar_file(filename) # 递归返回
yield i # 这样 内层的 yield 就可以逐级返回到最外层了
continue
image.png
第二种方法:yield from
https://www.python.org/dev/peps/pep-0380/
yield from self.iter_tar_file(filename)
image.png
yield from 用于把子级迭代器 返回到外面 效果是等同于 for 循环的
可以这样想
def a():
if xxx:
for i in iter :
yield i
yield xx
这样所有的yield 值都可以返回给最外面的函数了,yield 也起到了for 循环的效果,但是更简洁,是 pep 8 规范呢
递归的如果需要 yield 返回数据,需要 用 for 循环嵌套,或者跟简单就是 用 yield form iterobj 返回 不yield 后者直接yield 都拿不到数据
网友评论