Python 在 print() 之后跳过 for 循环

Posted

技术标签:

【中文标题】Python 在 print() 之后跳过 for 循环【英文标题】:Python skipping for-loop after print() 【发布时间】:2016-02-26 09:59:04 【问题描述】:

我正在调试编写代码的部分,所以我使用大量对print 的调用来检查我的变量的值。我遇到了一种情况,当打印一个变量时,Python 会跳过一个 for 循环。

import numpy as np
import itertools as itr
(...)

class myclass():
    def a_function_inside_a_class():
        print('-------------')
        current_size = self.get_current_size()
        current_size[dimension] += 1

        new_layer = [range(i) for i in current_size]
        new_layer[dimension] = [current_size[dimension]]
        print(new_layer)

        new_layer = itr.product(*new_layer)
        print(list(new_layer)) # THIS LINE CAUSES PROBLEMS

        for c in new_layer:
            print('for')
            print(list(c))
            (...)
            a_function_that_causes_some_error(c)

我创建一个列表,然后使用itertools 创建此列表的组合,然后对其进行迭代。 如果我像上面那样调用a_function_inside_a_class()我没有打印出for。没有错误发生。解释器没有进入循环。

(...)
-------------
[[2], range(0, 1), range(0, 1)]
[(2, 0, 0)]
-------------
[range(0, 1), [2], range(0, 1)]
[(0, 2, 0)]
(...)

但如果我注释掉#print(list(new_layer)),则执行for循环,我得到一个由其他函数a_function_that_causes_some_error(c)引起的错误。

-------------
[[2], range(0, 1), range(0, 1)]
for
[2, 0, 0]
Traceback (most recent call last):
(...)

list(new_layer) 不会改变new_layer 对象本身,只会创建一个列表并将其传递给print() 函数,是吗?

【问题讨论】:

为什么函数体内有self,但函数的参数列表中没有? 只需在第一次调用之后的行中添加另一个print(list(new_layer)),您就会明白它为什么会失败。 print 不是问题,list() 是。 itertools.product() 是一个生成器,当您在其上使用 list() 时,您已经耗尽了迭代器。改为在列表中添加for @cdarke - 你把它宠坏了!我想在不泄露的情况下暗示这个事实。但你完全正确! :-) @MSeifert:我在写文档时正在检查我的评论,所以我错过了你的评论。很抱歉破坏了你的乐趣! 【参考方案1】:

问题是itertools.product 返回了一个生成器。

当您调用 print(list(new_layer)) 时,您正在从生成器构造一个列表,但不要在任何地方保存对该列表的引用。

生成器本身在将其转换为列表后将耗尽,因为list(some_generator) 在该生成器上调用__next__(或next,取决于Python 版本)直到它引发StopIteration

>>> from itertools import product
>>> new_layer = product([1,2,3], [4,5,6])
>>> new_layer
<itertools.product object at 0x7f46e90349b0>
>>> print(list(new_layer))
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
>>> print(list(new_layer))
[]

如你所见,构造列表一次后,生成器为空。

你可以通过使用来修复你的程序

new_layer = list(itr.product(*new_layer))
print(new_layer)

因为现在您将获得对从生成器创建的列表的引用。

【讨论】:

您的建议有效,但它与在他的情况下使用itertools 完全矛盾,因为您将结果保存在应该只保留生成器的地方。这里的教训应该是:不要在循环之前调试循环变量,在循环中调试/显示它们 @MSeifert 是的,据我了解 OP,他正在使用打印调用进行调试。我建议在程序经过正确测试之前使用我的修复程序。然后,在删除打印语句后,不再需要将生成器转换为列表,如果您按原样使用生成器,程序将更加节省内存。

以上是关于Python 在 print() 之后跳过 for 循环的主要内容,如果未能解决你的问题,请参考以下文章

python 学习笔记(循环,print的几种写法,操作符)

学习两个Python不常用的语法

python读取csv文件跳过前几行

Python:如果条件为真,则跳过 For 循环中的迭代

为啥 Python for 循环在遍历列表副本并进行删除时会跳过元素? [复制]

Python_循环总结