简体   繁体   English

for循环中的Python异常处理

[英]Python exception handling inside for loop

I am new to Python, and programming in general. 我是Python新手,也是一般编程人员。 While I think this question may be related to my use of exception handling, it might also be due to a general lack of understanding! 虽然我认为这个问题可能与我使用异常处理有关,但也可能是由于普遍缺乏理解!

for i in range(0, len(dates)):
    try:
        data.append(WUF.getwx(location[j], dates[i])[1])
        continue
    except xml.etree.ElementTree.ParseError:
        #copy last good row of data and use it for the missing day
        fixdata = data[-1] #[1,2,3,4,5,6,7,8,9,10,11]
        fixdata[10] = 'estimated'
        data.append(fixdata)

When I run the code as written, I get 2 "estimated" lines in data . 当我按编写的方式运行代码时,我在data得到2个“估计”行。 One for the previous date, and one for the date that is being estimated. 一个用于上一个日期,一个用于估计的日期。 If I change the fixdata variable to [1, 2, 3, 4, 5, ...] , then only one line (the intended line for the estimated date) is "estimated". 如果我将fixdata变量更改为[1, 2, 3, 4, 5, ...] ,那么只有一行(估计日期的预期行)是“估计”。

Any idea what I'm missing here? 知道我在这里缺少什么吗? Thanks! 谢谢!

The issue is in the line: 问题在于:

fixdata = data[-1]

That doesn't actually copy the data, it only copies the reference to the data. 这实际上并不复制数据,它只复制对数据的引用 fixdata ends up pointing to the original element in the list, so when you then do fixdata最终指向列表中的原始元素,所以当你这样做时

fixdata[10] = 'estimated'

it changes the original data. 它改变了原始数据。

To actually copy the data, try this: 要实际复制数据,请尝试以下操作:

fixdata = data[-1][:]

[:] copies the whole list, which is what I think you're trying to do. [:]复制整个列表,这是我认为您正在尝试做的事情。

It sounds like you are appending lists to your data list -- creating a 'list of lists'. 听起来您正在将列表附加到data列表中 - 创建“列表列表”。

That's good -- I'm sure it's what you are intending to do. 这很好 - 我确信这是你打算做的。 But in your exception handler, you are actually modifying existing data: 但是在您的异常处理程序中,您实际上是在修改现有数据:

fixdata = data[-1]

This line assigns a reference to the last row in data to fixdata . 此行将data最后一行的引用分配给fixdata At this point, fixdata and data[-1] are the same object . 此时, fixdatadata[-1]同一个对象 So, when you do this: 所以,当你这样做时:

fixdata[10] = 'estimated'

Then the list you are 'fixing' is still inside the data list, as well as being referenced by the name fixdata . 然后,您正在“修复”的列表仍在data列表中,并且由名称fixdata引用。 Two names, one object in memory. 两个名字,一个记忆中的对象。

When you append it again, with 当你再次追加它时,用

data.append(fixdata)

You still aren't copying it; 你仍然没有复制它; Now, you actually have two references to the very same object inside your data list. 现在,您实际上有两个对data列表中同一对象的引用。 This is why it looks like you have two 'estimated' lines -- they're one and the same object. 这就是为什么看起来你有两条'估计'线 - 它们是同一个对象。

What you really want to do is to make a copy of the last row, rather than just a reference to it. 你真正想要做的是复制最后一行,而不仅仅是对它的引用。 Change your code to this: 将您的代码更改为:

for i in range(0, len(dates)):
    try:
        data.append(WUF.getwx(location[j], dates[i])[1])
        continue
    except xml.etree.ElementTree.ParseError:
        #copy last good row of data and use it for the missing day                 
        fixdata = data[-1][:] #[1,2,3,4,5,6,7,8,9,10,11]
        fixdata[10] = 'estimated'                
        data.append(fixdata)

The syntax list[:] is a shorthand for 'each element of this list', and is used as a quick copy operation. 语法列表[:]是“此列表的每个元素”的简写,用作快速复制操作。 Then fixdata will be its own list, and you can change elements of independently of the original. 然后fixdata将是它自己的列表,您可以更改独立于原始元素。

A couple more comments about your original code sample (outside of the scope of your question) 关于原始代码示例的更多评论(在您的问题范围之外)

  1. You never actually use the i variable, except to index back into the dates list. 除了索引回日期列表之外,你永远不会真正使用i变量。 One of Python's strengths is its iterators: you can iterate your for loop directly over the items in the list, without having to count them and use an index variable: Python的优势之一是它的迭代器:你可以直接在列表中的项目上迭代你的for循环,而不必计算它们并使用索引变量:

     for date in dates: 
  2. Your continue statement doesn't actually do anything. 你的继续声明实际上没有做任何事情。 continue tells the interpreter to finish this iteration of the for loop immediately, and start the next iteration right away. continue告诉解释器立即完成for循环的迭代,并立即开始下一次迭代。 In this case, there are no statements after the continue statement, so the loop would continue naturally, without being told to. 在这种情况下,在continue语句之后没有语句,因此循环将自然地继续,而不被告知。

  3. There really isn't a need to build up the fixdata variable in two statements, append it in a third, and then discard it (We're discarding the fixdata variable, not its contents) You could do it more succinctly like this: 确实没有必要在两个语句中构建fixdata变量,将它附加到第三个,然后丢弃它(我们丢弃了fixdata变量,而不是它的内容)你可以更简洁地这样做:

     data.append(data[-1][:10] + ['estimated']) 

    In one line, this copies the first 10 elements of the last row into a new list, adds the (very short) list ['estimated'] to the end, and appends it. 在一行中,这会将最后一行的前10个元素复制到一个新列表中,将(非常短的)列表['估计']添加到结尾,然后附加它。

  4. Your code will run into problems if your very first row throws an exception -- in that case, you won't be able to access data[-1] -- trying to do so will throw another exception, which will propagate up. 如果您的第一行抛出异常,您的代码将遇到问题 - 在这种情况下,您将无法访问data[-1] - 尝试这样做会抛出另一个异常,它将向上传播。 Better to guard against that like this: 最好这样防范:

     except xml.etree.ElementTree.ParseError: if data: # do something 

Putting it all together, I would write the code more like this: 把它们放在一起,我会写代码更像这样:

for date in dates:
    try:
        data.append(WUF.getwx(location[j], date)[1])
    except xml.etree.ElementTree.ParseError:
        # as long as we've parsed at least one good row
        if data:
            # copy last good row of data and use it for the missing day
            data.append(data[-1][:10] + ['estimated'])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM