2008-11-03 79 views
11

我最近被意外的東西咬了。我想這樣做:爲什麼異常是可迭代的?

try : 
    thing.merge(iterable) # this is an iterable so I add it to the list 
except TypeError : 
    thing.append(iterable) # this is not iterable, so I add it 

嗯,它工作正常,直到我傳遞了一個對象,繼承應該被添加的異常。

不幸的是,異常是可迭代的。以下代碼不會引發任何TypeError

for x in Exception() : 
    print 1 

有人知道爲什麼嗎?

回答

11

請注意,發生的事情與任何類型的隱式字符串轉換等無關,但是因爲Exception類實現了__getitem __(),並使用它來返回args元組(ex.args)中的值。你可以看到這一點,你得到的整個字符串作爲迭代中的第一個也是唯一的一個項目,而不是你迭代字符串時得到的逐字符結果。

這也讓我感到驚訝,但考慮到這一點,我猜這是出於向後兼容的原因。 Python曾經(pre-1.5)缺少當前的異常類層次結構。相反,字符串被拋出,通常是一個元組參數,用於傳遞給處理塊的任何細節。即:

try: 
    raise "something failed", (42, "some other details") 
except "something failed", args: 
    errCode, msg = args 
    print "something failed. error code %d: %s" % (errCode, msg) 

它看起來像這樣的行爲被投入,以避免破壞前的1.5代碼期​​待的參數的元組,而不是一個非迭代異常對象。在上面的致命破解部分中有IOError的幾個例子link

字符串異常已被定義了一段時間,並且正在Python 3中消失。我現在已經檢查了Python 3如何處理異常對象,它看起來像他們不再有可迭代:

>>> list(Exception("test")) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'Exception' object is not iterable 

[編輯]經過python3的行爲

3

無效。檢查Brian anwser。

好吧,我剛剛纔:

for x in Exception("test") : 
    print x 
    ....:  
    ....:  
test 

不要打擾;-)

無論如何,這是很好的瞭解。

編輯:期待的意見,我覺得像添加一些解釋。

例外包含您實例化過程中傳遞的消息:

raise Exception("test") 

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Exception: test 

公平地說,消息是什麼定義異常最好的,所以STR()返回它:

print Exception("test") 
test 

現在,在異常情況以外的情況下,異常被隱式轉換爲字符串。

所以,當我做的:

for x in Exception("test") : 
    print x 

我遍歷字符串 「測試」。

當我做:

for x in Exception() : 
    print x 

我遍歷一個空字符串。棘手。因爲當涉及到我的問題:

try : 
    thing.merge(ExceptionLikeObject) 
except TypeError : 
    ... 

這不會引發任何事情,因爲ExceptionLikeObject被視爲一個字符串。

現在,我們知道如何,但我仍然不是爲什麼。也許內置的Exception繼承自內建的String?因爲據我所知:

  • 加入str不會使任何對象迭代。
  • 我繞過這個問題,因爲overloding iter,使它引發TypeError!

不再是問題,但仍然是一個謎。

+0

其實它不是把它當作一個字符串,它是把它當作參數元組。即list(Exception(「test」))== [「test」],而不是[「t」,「e」,「s」,「t」]。同樣列表(Exception(1,2))== [1,2]。有關這可能是爲什麼的猜測,請參閱下面的答案。 – Brian 2008-11-03 15:22:53

2

其實我還是不太明白。我可以看到迭代一個異常給你的原始參數的異常,我只是不知道爲什麼有人會想要的。隱式迭代是我認爲Python中的幾個陷阱之一,仍然讓我起牀。

+0

這不是隱式迭代導致的,它是隱式轉換。異常會自動轉換爲字符串,這是可迭代的。 – 2008-11-03 13:12:38

+0

投票原因我認爲這是不公平的,因爲你不明白和投票。我會在答案中加入更多解釋。 – 2008-11-03 14:15:43