2012-03-23 5 views
19

私はそれは、Python 2.7で例外を発生させる際に行うことができますミスについてです、つらい時、このいずれかを考え出すを持っている:最初の要素が例外の場合、タプルを呼び出すのはなぜですか?

try: 
    raise [1, 2, 3, 4] 
except Exception as ex: 
    print ex 

ここでのメッセージは、例外はBaseExceptionから導出古いスタイルのクラスまたはでなければなりません」です例外は、int型、古いスタイルのクラスやBaseException由来であってはならないこと 『: - 「

try: 
    raise (1, 2, 3, 4) 
except Exception as ex: 
    print ex 

ここにメッセージがある。この部分はOKですが、私はタプルに変更したときに、私は混乱しています』、表示しませんなぜそれがタプルではなくintを上げると解釈されますか?

Futhermore:ここ

try: 
    raise (Exception, 'a message') 
except Exception as ex: 
    print ex 

我々は実際に(私たちはINTを上げた前の例と比較すると、一貫性のある動作)例外を上昇している - 私は簡単にこれは、このためだけの別の方法であると考えました:

try: 
    raise Exception, 'a message' 
except Exception as ex: 
    print ex 

しかし、この場合には、 'メッセージ' は例外CTORに渡されている(docs.python.orgに文書化されているように)

できる人expla 2番目と3番目のケースでは、可能性があります私はこれを担当している通訳でコードを指す?

答えて

15

は、raise文は例外を作成するために、3式に取り提起されている:

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

のpython 2では、最初の式がタプルであれば、Pythonの意志「アンラップ」再帰的タプル、それがタプル以外の何かを見つけるまで最初の要素を取ります。この動作はPython 3から削除されています(PEP 3109参照)。以下は合法です:

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

ドキュメントは、より詳細に休息を説明しますが、raise文は、最初の値がExceptionクラスであることを期待、第二の値は、例外(メッセージ)の値として見られています3番目の値はトレースバックです。行方不明の場合、Pythonは後の2つの値のためにNoneを埋めます。

最初の値ではなく、第二の値 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 

あなたが3つの以上の項目のタプルを使用する場合は、構文を上げますエラー:お使いの場合には

>>> raise Exception, 'something', None, None 
    File "<stdin>", line 1 
    raise Exception, 'something', None, None 
            ^
SyntaxError: invalid syntax 

しかし、あなたはクラスでもインスタンスでもないを上げたので、それは、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 

正しい構文はもちろんです:

>>> raise Exception, 'something', None 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Exception: something 
+0

私は再帰的タプルのアンラップを認識していなかったので、他の要素が無視されている理由を知ることができませんでした.PEPは私が探していた欠落したリンクでした。 – dahpgjgamgan

3

http://docs.python.org/reference/simple_stmts.html#the-raise-statement

"昇給" [表現[ "" 表現の[ "" 表現]]]

何の表現が存在しない場合は、中にアクティブであった最後の例外を再発生させ上げます現在のスコープ... raiseは、省略された式の値としてNoneを使用して、式を評価して3つのオブジェクトを取得します。最初の2つのオブジェクトは、例外のタイプと値を決定するために使用されます。

実は、私はPythonがここに

try: 
    raise (ValueError, "foo",), "bar" 
except Exception as e: 
    print e.message # foo or bar? 

を開梱タプルんが、それがなかった場合、結果は "foo" という、およびない "バー" だろうと思いました。この動作は、どこにも文書化されていないよう、それはPY3にドロップされた程度だけ短いメモがあります:documented in the python referenceとして

In Python 2, the following raise statement is legal

raise ((E1, (E2, E3)), E4), V

The interpreter will take the tuple's first element as the exception type (recursively), making the above fully equivalent to

raise E1, V

As of Python 3.0, support for raising tuples like this will be dropped. This change will bring raise statements into line with the throw() method on generator objects, which already disallows this.

http://www.python.org/dev/peps/pep-3109/#id17

+1

私はその質問にどのように答えますか。説明するケア? –

+1

私のコメントについてもう少し明確にする:タプルが評価され、最初の要素が返されることは明らかです。なぜこれはリスト引数では起こりませんか? –

+0

タプルは自動的に解凍され、リストは解凍できませんでした。 – kosii

3

はどうやらPythonはまた、raise文の最初の式にもかかわらずのための非空のタプルを受け入れドキュメント(ただしthis PEPに記載されています)を返します。タプルの場合は、例外クラスの最初の要素を再帰的に使用します。私は私の以前のコメントで述べてきたものにもかかわらず

>>> raise ValueError, 'sdf', None 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: sdf 

>>> raise (ValueError, 5), 'sdf', None 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: sdf 

文字列は私の次の例では、例外クラスに渡されていないので、何の自動開梱は、ありません:私はあなたにいくつかのコードをお見せしましょう

>>> raise (ValueError, 'sdf', None) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError 

はまた、Pythonのastのモジュールを使用して、我々は昇給式で、デフォルトでは何のタプルが存在しないことがわかります。

>>> ast.dump(ast.parse('raise ValueError, "asd"')) 
"Module(body=[Raise(type=Name(id='ValueError', ctx=Load()), inst=Str(s='asd'), tback=None)])" 

そして、我々はタプルを使用している場合、そのは、型引数として渡されています:

>>> ast.dump(ast.parse('raise (ValueError, "asd")')) 
"Module(body=[Raise(type=Tuple(elts=[Name(id='ValueError', ctx=Load()), Str(s='asd')], ctx=Load()), inst=None, tback=None)])" 
関連する問題