我最近被一些意想不到的东西咬了。我想做出类似的东西:
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
嗯,它工作正常,直到我传递了一个继承自Exception的对象,该对象应该被添加。
不幸的是,异常是可迭代的。以下代码不会引发任何TypeError
:
for x in Exception() :
print 1
有人知道为什么吗?
答案 0 :(得分: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之前的代码,期望一个参数元组,而不是一个不可迭代的异常对象。在上面的link
的致命破损部分中,有几个这样的例子与IOError有关字符串异常已经被推迟了一段时间,并且在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的行为
答案 1 :(得分: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
公平地说,消息是最好的定义Exception,所以str()返回它:
print Exception("test")
test
现在,当Exceptions用于除Exception上下文以外的其他内容时,会发生异常被隐式转换为字符串。
所以当我这样做时:
for x in Exception("test") :
print x
我正在迭代字符串“test”。
当我这样做时:
for x in Exception() :
print x
我迭代一个空字符串。棘手。因为谈到我的问题:
try :
thing.merge(ExceptionLikeObject)
except TypeError :
...
由于ExceptionLikeObject被视为字符串,因此不会引发任何内容。
现在,我们知道如何,但我仍然不是为什么。也许内置的Exception继承自内置的String?因为据我所知:
不再是问题,但仍然是一个谜。
答案 2 :(得分:2)
实际上,我还是不太明白。我可以看到,迭代一个Exception会给你异常的原始args,我只是不确定为什么有人会想要这个。隐式迭代是我认为Python中为数不多的陷阱之一仍然让我兴奋不已。