In general we value conciseness. We don’t need # Case D: match! because that’s the intended behavior.
I think using three classes for the example is overkill – we can shorten the example by nearly 1/3rd if we just use classes B and C. We then get:
class B(Exception):
pass
class C(B):
pass
for cls in [B, C]:
try:
raise cls()
except C:
# Matches C but not B.
print("C")
except B:
# Matches B; not reached for C.
print("B")
And I would explicitly write out the reversed example:
for cls in [B, C]:
try:
raise cls()
except B:
# Matches B and C both.
print("B")
except C:
# Not reached (the previous clause ate B and C)
print("C")