Di tempat kerja, saya menemukan except
klausa dengan or
operator:
try:
# Do something.
except IndexError or KeyError:
# ErrorHandling
Saya tahu kelas pengecualian harus lulus sebagai tuple, tapi itu menyadap saya bahwa itu bahkan tidak akan menyebabkan a SyntaxError
.
Jadi pertama saya ingin menyelidiki apakah itu benar-benar berfungsi. Dan ternyata tidak.
>>> def with_or_raise(exc):
... try:
... raise exc()
... except IndexError or KeyError:
... print('Got ya!')
...
>>> with_or_raise(IndexError)
Got ya!
>>> with_or_raise(KeyError)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in with_or_raise
KeyError
Jadi itu tidak menangkap pengecualian kedua, dan melihat bytecode, menjadi lebih jelas mengapa:
>>> import dis
>>> dis.dis(with_or_raise)
2 0 SETUP_EXCEPT 10 (to 12)
3 2 LOAD_FAST 0 (exc)
4 CALL_FUNCTION 0
6 RAISE_VARARGS 1
8 POP_BLOCK
10 JUMP_FORWARD 32 (to 44)
4 >> 12 DUP_TOP
14 LOAD_GLOBAL 0 (IndexError)
16 JUMP_IF_TRUE_OR_POP 20
18 LOAD_GLOBAL 1 (KeyError)
>> 20 COMPARE_OP 10 (exception match)
22 POP_JUMP_IF_FALSE 42
24 POP_TOP
26 POP_TOP
28 POP_TOP
5 30 LOAD_GLOBAL 2 (print)
32 LOAD_CONST 1 ('Got ya!')
34 CALL_FUNCTION 1
36 POP_TOP
38 POP_EXCEPT
40 JUMP_FORWARD 2 (to 44)
>> 42 END_FINALLY
>> 44 LOAD_CONST 0 (None)
46 RETURN_VALUE
Jadi bisa kita lihat, instruksi 14 pertama memuat IndexError
kelas ke stack. Kemudian memeriksa apakah nilai itu True
, yang karena kebenaran Python dan akhirnya melompat langsung ke instruksi 20 di mana exception match
dilakukan. Karena instruksi 18 dilewati, KeyError
tidak pernah dimuat ke tumpukan dan karenanya tidak cocok.
Saya mencoba dengan Python 2.7 dan 3.6, hasilnya sama.
Tetapi, mengapa sintaksis itu valid? Saya membayangkannya sebagai salah satu dari yang berikut:
- Ini adalah artefak dari versi Python yang sangat lama.
- Sebenarnya ada use case yang valid untuk digunakan
or
dalamexcept
klausa. - Ini hanyalah batasan dari pengurai Python yang mungkin harus menerima ekspresi apa pun setelah
except
kata kunci.
Suara saya ada di 3 (mengingat saya melihat beberapa diskusi tentang parser baru untuk Python) tapi saya berharap seseorang dapat mengkonfirmasi hipotesis itu. Karena kalau itu 2 misalnya, saya ingin tahu use case itu!
Juga, saya agak tidak mengerti tentang bagaimana saya melanjutkan eksplorasi itu. Saya membayangkan saya harus menggali kode sumber CPython parser tetapi idk di mana menemukannya dan mungkin ada cara yang lebih mudah?