2013-01-03 47 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"