今天看MAE代码的过程中,发现了enumerate配合yeild函数一起出现,弄得我是晕头转向,在查了一些资料后,总结如下。
目录
先对比三段代码
MAE中的代码段:
调用log_every的代码段
for data_iter_step, (samples, _) in enumerate(metric_logger.log_every(data_loader, print_freq, header)): ..... samples = samples.to(device, non_blocking=True) .....
log_every函数的声明以及部分代码段
def log_every(self, iterable, print_freq, header=None): ....... for obj in iterable: ..... yield obj ....
测试代码段
a = [0, 1, 2, 3, 4, 5] # 定义一个列表 def test(a:list): # 定义函数test,相当于MAE中的metric_logger.log_every for i in a: yield i print("进入下一层循环!!!") for idx, sample in enumerate(test(a)): # for循环配合enumerate和yield print(idx, " -----", sample)
对应的输出如下
0 ----- 0 进入下一层循环!!! 1 ----- 1 进入下一层循环!!! 2 ----- 2 进入下一层循环!!! 3 ----- 3 进入下一层循环!!! 4 ----- 4 进入下一层循环!!! 5 ----- 5 进入下一层循环!!!
三段代码的分析
mae代码段
MAE中的log_every并没有return,但是有yield,每次调用yield的时候,会返回obj这个对象,而这个对象的值会返回给enumerate函数进行迭代,并赋值给(sample, _)。
对比代码段
第一次for循环调用test函数时,会进入test函数中的for循环,执行yield i ,于是返回i给enumerate函数,第二次for循环调用test时,会先调用其中的print函数,然后再进入下一次for循环(test函数中的),并调用yield,如此往复即可得到输出的结果。
疑惑
但是本人还不是特别理解idx(测试代码段中)怎么来的,虽说enumerate可以返回idx,但是yield每次只产生一个数值,具体的原因可能时enumerate函数的作用,如果有小伙伴有更好的解答,欢迎评论区留言。