2013-01-03 46 views
1

我跑的代码的此块并得到类似下面的错误:奇怪的运行时错误而迭代的字典

Traceback (most recent call last): 
    File "urllister.py", line 26, in <module> 
    for k in l: print k,"points to",l[k],"\n" 
RuntimeError: dictionary changed size during iteration 

我唯一要做的是在在线路环路27

from sgmllib import SGMLParser 

class URLLister(SGMLParser): 
    def reset(self): 
     SGMLParser.reset(self) 
     self.data = [] 
    def start_a(self, attrs): 
     href = [v for k , v in attrs if k == 'href'] 
     if href: 
      self.data.extend(href) 

if __name__ == '__main__': 
    import urllib 
    sock = urllib.urlopen("http://diveintopython.org") 

    parser = URLLister() 
    html = sock.read() 

    parser.feed(html) 

    sock.close() 
    parser.close() 
    for url in parser.data: print url 
    l = locals() 

    for k in l: 
     print k,"points to",l[k],"\n" 
+0

在迭代它时,您无法更新或编辑字典。 –

回答

10
打印

原因是你循环引入了一个新的局部变量,k,这意味着你的循环中你的局部变量字典被改变了。

最简单的解决方案(如果您真的需要这样做,尽管这通常是个不好主意的标志)是复制字典 - 例如:l = dict(locals())。这样,更新的原始文件不会导致问题。

+0

你是正确的介绍一个新的变量k,但在书“diveinto python”http://www.diveintopython.net/html_processing/locals_and_globals.html locals()已经返回该字典的副本 – kun

+1

根据python doc http ://docs.python.org/2/library/functions.html#locals,这不是python 2.7.3的副本。 Lattyware是对的。 Diveintopython可能不是最新的 – trez

+1

@cjk:这本书使用了不幸的词语选择。作者试图解释修改'locals()'不会改变变量的原因 - 但实际上,它有时可以(例如,在CPython中,如果你不从函数内部完成)。如果你忘记了有时候它确实起作用的事实,那么调用'locals()'的一个副本和'globals()'的结果不是一个副本,这给你一个粗略的想法。但是'a = locals()''b = locals()''print a is b'给出'True'; 'locals()'不返回一个副本。 – DSM

0

错误的原因是,Python认为,由于您通过键访问字典,您可以更改字典,这是在这里限制。为了避免这种错误,你可以使用get方法,你的声明将是这样的,那么:

for k in l: 
    print k,"points to",l.get(k),"\n" 
0

这样做的原因是,你循环引入了一个新的局部变量,K,这意味着你的局部变量的字典在循环中被改变。

最简单的解决方案是在循环前定义k,这样locals()在循环开始后不会改变。

k = 0 
l = locals() 

for k in l: 
    print k,"points to",l[k],"\n"