如果第一个元素是异常,为什么提高元组有效?

dah*_*gan 22 python tuples exception python-2.7

我很难搞清楚这一点,它是关于在Python 2.7中引发异常时可以做的错误:

try:
  raise [1, 2, 3, 4]
except Exception as ex:
  print ex
Run Code Online (Sandbox Code Playgroud)

这里的消息是"异常必须是旧式类或派生自BaseException,而不是列表" - 这部分没问题,但当我将其更改为元组时,我感到困惑:

try:
  raise (1, 2, 3, 4)
except Exception as ex:
  print ex
Run Code Online (Sandbox Code Playgroud)

这里的消息是"异常必须是旧式类或派生自BaseException,而不是int" - 为什么它被解释为引发int,而不是元组?

Futhermore:

try:
  raise (Exception, 'a message')
except Exception as ex:
  print ex
Run Code Online (Sandbox Code Playgroud)

在这里,我们实际上提出了一个异常(与之前的示例相比,我们提出了一个int的一致行为) - 我简单地认为这只是另一种方式:

try:
  raise Exception, 'a message'
except Exception as ex:
  print ex
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,"消息"正被传递给Exceptions ctor(如docs.python.org上所述)

有人可以解释第二和第三种情况,并可能指出我在解释器中编写代码吗?

Mar*_*ers 16

Python 2参考中所述,该raise语句最多需要3个表达式来创建引发的异常:

raise_stmt :: ="raise"[expression [","expression [","expression]]]

如果第一个表达式是一个元组,python将递归地'解包'元组,取第一个元素,直到找到除元组之外的其他元素.从Python 3中删除了此行为(请参阅PEP 3109).以下是合法的:

>>> raise ((Exception, 'ignored'), 'ignored'), 'something', None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: something
Run Code Online (Sandbox Code Playgroud)

文档更详细地解释了其余部分,但raise语句期望第一个值是Exception类,第二个值被视为异常(消息)的值,第三个值是回溯.None如果缺少Python,Python会填写后两个值.

如果第一个值是实例,则第二个值必须为None:

>>> raise Exception('something'), 'something', None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: instance exception may not have a separate value
Run Code Online (Sandbox Code Playgroud)

如果您使用超过3项的元组,则会引发语法错误:

>>> raise Exception, 'something', None, None
  File "<stdin>", line 1
    raise Exception, 'something', None, None
                                      ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

但是,在你的情况下,你既没有提出类也没有实例,所以这就是Python首先发现的错误; 如果我使用字符串,它也会抱怨:

>>> raise 'not an exception', 'something', None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: exceptions must be old-style classes or derived from BaseException, not str
Run Code Online (Sandbox Code Playgroud)

正确的语法当然是:

>>> raise Exception, 'something', None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: something
Run Code Online (Sandbox Code Playgroud)