İş except
yerinde, bir or
operatörle bir maddeye rastladım :
try:
# Do something.
except IndexError or KeyError:
# ErrorHandling
İstisna sınıflarının bir demet olarak geçmesi gerektiğini biliyorum, ama bunun bir neden bile olmayacağı beni rahatsız etti SyntaxError
.
İlk olarak gerçekten işe yarayıp yaramadığını araştırmak istedim. Ve öyle değil.
>>> 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
Bu yüzden ikinci istisnayı yakalamadı ve bayt koduna baktığımızda, neden daha açık hale geliyor:
>>> 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
Gördüğümüz gibi, talimat 14 önce IndexError
sınıfı yığına yükler . Daha sonra bu değerin True
Python gerçeği nedeniyle olup olmadığını kontrol eder ve nihayet doğrudan exception match
yapıldığı talimat 20'ye atlar . Talimat 18 atlandığından, KeyError
asla yığına yüklenmedi ve bu nedenle eşleşmiyor.
Aynı sonucu Python 2.7 ve 3.6 ile denedim.
Peki, neden geçerli bir sözdizimi? Aşağıdakilerden biri olduğunu hayal ediyorum:
- Python'un gerçekten eski bir versiyonundan gelen bir eser.
- Aslında
or
birexcept
cümle içinde kullanmak için geçerli bir kullanım durumu vardır . - Python ayrıştırıcısının,
except
anahtar kelimeden sonra herhangi bir ifadeyi kabul etmesi gerekebilecek bir sınırlamasıdır .
Benim oyum 3 (Python için yeni bir ayrıştırıcı hakkında bazı tartışmalar gördüm verilen) ancak birisinin bu hipotezi doğrulayabileceğini umuyorum. Çünkü mesela 2 ise, bu kullanım durumunu bilmek istiyorum!
Ayrıca, bu araştırmaya nasıl devam edeceğim konusunda da biraz fikrim yok. CPython ayrıştırıcısının kaynak kodunu kazmak zorunda kalacağımı hayal ediyorum ama idk'i nerede bulabilirim ve belki daha kolay bir yol var mı?