For循环不会遍历所有对象

时间:2015-06-16 11:25:15

标签: python list for-loop

为什么这个for循环不会遍历所有项目:

 temp = 0

 for br in my_list :
    temp +=1
    #other code here
    #my list is not used at all, only br is used inside here
    my_list.remove(br)

 print temp
 assert len(my_list) == 0 , "list should be empty"

所以,断言开火了。然后我添加了临时计数器,我确实看到尽管我的列表有202个元素,但for循环只处理了101个元素。那是为什么?

4 个答案:

答案 0 :(得分:5)

您不应该从正在迭代的列表中删除。如果你想删除东西,请使用此

while list:
   item = list.pop()
   #Do stuff

修改:如果您想了解pop()的更多信息,请查看python doc

如果订单很重要,请使用pop(0)pop()默认情况下会移除最后一项,如果您想按顺序浏览列表,则应使用pop(0)删除第一个(索引0)项并将其返回。

Edit2:感谢用户Vincent提出while list建议。

答案 1 :(得分:3)

for br in my_list :替换为for br in my_list[:] :。多亏了你将要遍历源列表的副本。

答案 2 :(得分:2)

tobias_k正确删除正在迭代的列表中的项目会导致各种问题。

在这种情况下,通过使用repl打印每个循环上的列表,相对容易地显示它导致迭代跳过:

[1, 2, 3, 4, 5]
[1, 3, 4, 5]
[1, 3, 5]

这会产生:

my_list = [0,1,2,3,4,5]
for br in my_list[:]:     #The [:] takes a copy of my_list and iterates over it
  my_list.remove(br)
  print my_list

最后留下my_list包含:[1,3,5]

要做你想做的事,mic4ael是正确的,最简单的(尽管可能不是最有效的)方法是在迭代之前获取列表的副本,如下所示:

[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[5]
[]

这会产生:

 def generate_pdf_voucher(voucher, dir_name)
    view = ActionView::Base.new(Rails.root.join('app/views'))
    view.class.include ApplicationHelper
    view.class.include Rails.application.routes.url_helpers

    pdf = view.render :pdf => a_name,
                      :template => 'layouts/pdfs/voucher_pdf',
                      :layout => 'layouts/pdfs/pdf.html.erb',
                      :header => {:right => '[page] of [topage]'},
                      :locals => {:@voucher => voucher}
    # then save to a file
    pdf = WickedPdf.new.pdf_from_string(pdf)

    save_path = Rails.root.join('public', 'pdfs', dir_name, "#{voucher[:user].id.to_s}.pdf")
    File.open(save_path, 'wb') do |file|
      file << pdf
    end
end

答案 3 :(得分:0)

如果你真的需要尽快回收列表中的项目使用的内存,你可以像这样释放它们

for i, br in enumerate(my_list):
    #other code here
    my_list[i] = None

除了在Jython中,Java会在它感觉到它时释放它们