为什么这个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个元素。那是为什么?
答案 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会在它感觉到它时释放它们