2008-11-03 54 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

相关问题