使用类在python中进行异常处理
我对python例外情况表示怀疑。 下面的代码取自python文档,有一点我很困惑。如果有人能帮忙,我会很感激的。 此处,该代码给出如下输出: B、C、D 如果我更改除以下代码以外的部分代码: 输出将是: B B B 当我不使用try块运行此代码时,如下所示:使用类在python中进行异常处理,python,python-3.x,exception-handling,Python,Python 3.x,Exception Handling,我对python例外情况表示怀疑。 下面的代码取自python文档,有一点我很困惑。如果有人能帮忙,我会很感激的。 此处,该代码给出如下输出: B、C、D 如果我更改除以下代码以外的部分代码: 输出将是: B B B 当我不使用try块运行此代码时,如下所示: class B(Exception): pass class C(B): pass class D(C): pass for cls in [B, C, D]: raise cls() 这里的输出是: T
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
raise cls()
这里的输出是:
Traceback (most recent call last):
File "C:/Users/885710/Documents/PY/ErrorHandling.py", line 12, in <module>
raise cls()
B
输出是这个吗
Traceback (most recent call last):
File "C:/Users/885710/Documents/PY/ErrorHandling.py", line 12, in <module>
raise cls()
C
即使为所有3个B、C、D类定义了except,因为
B
是C
和D
的超类,您的第二个版本将始终为B
使用第一个except
块。因为Python运行时将从上到下搜索匹配的,除了块。如果异常是except
块中类的实例,则except
块匹配。例如,如果抛出一个实例C
,该块将匹配,因为C()
也是B
的实例
根据经验法则,except
语句必须从最具体的条件减少到最一般的条件,例如。g、 :
try:
throw ...
except D: # the most specific class
print("D")
except C: # is more specific than B but less than D
print("C")
except B: # the most general class in your hierarchy
print("B")
except BaseException as e: the most general exception class
print(e.__class__.__name__)
说:
except子句中的类与异常(如果是)兼容
同一类还是基类
因此,给定代码:
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
可简化为以下内容:
for cls in [B, C, D]:
foo = cls()
if isinstance(foo, D):
print("D")
elif isinstance(foo, C):
print("C")
elif isinstance(foo, B):
print("B")
然后,您的修改将变成:
for cls in [B, C, D]:
foo = cls()
if isinstance(foo, B):
print("B")
elif isinstance(foo, C):
print("C")
elif isinstance(foo, D):
print("D")
因此,无论foo
是B
,C
还是D
的实例,它都将满足第一种情况,因为isinstance
也会为子类的实例生成True
。<
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
B->基类
C->从B继承
D->从C和C继承->从B继承
因此,D->继承自B和C
对于不同的异常,try语句可能有多个except子句。但最多只执行一个例外条款
除非捕获引发的异常,否则基类将被赋予捕获的优先级。i、 e当继承异常类时,except
中的优先级被赋予基类(在代码中是类B
)
第一个案例:
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
迭代1
:
要素:B
首先控件检查除了D
,因为它不是基类,也不是与提升的类匹配的类,然后控件将移动到除了C
,最后它将执行除了B
,从而打印B
迭代2
:
元素:C
首先控件检查除了D
,因为它不是基类,也不是与提升的类匹配的类,然后控件将移动到除了C
,并将执行除了C
,从而打印C
迭代3
:
元素:D
首先控件检查,除了D
,因为它是一个匹配的类,然后控件将
执行除D之外的,从而打印D
现在考虑第二种情况:
for cls in [B, C, D]:
try:
raise cls()
except B:
print("B")
except C:
print("C")
except D:
print("D")
这里B
是类C
和D
的基类,因此当您在except堆栈的顶部写入except B
时,控件不会转到后续的except C
和except D
。因此,对于for循环的每次迭代,它都将输出打印为B
。C是B,D是C(依次是B),因此(传递地)D是B(这就是继承的全部内容)。您尝试处理异常的顺序很重要(在本例中)。也许您应该从Exception扩展所有类(而不是像现在这样从一个类扩展到另一个类),这样您就可以在第二个代码片段中获得所需的行为(而不改变其他场景)<代码>C类(异常):
,D类(异常):
。也许你应该从异常扩展所有的类>>你能用例子解释一下吗?如果D是C,C是B,因此D是B,那么为什么它在第一个代码段中打印B,C,D,在第二个代码段中打印B,B,B。仍然没有得到重点,因为is只是一种方式:C是B,但B不是C。好的,谢谢你。。明白了,好极了!非常感谢你的解释。谢谢你再加上一个解释。帮了大忙!
for cls in [B, C, D]:
foo = cls()
if isinstance(foo, B):
print("B")
elif isinstance(foo, C):
print("C")
elif isinstance(foo, D):
print("D")
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
for cls in [B, C, D]:
try:
raise cls()
except B:
print("B")
except C:
print("C")
except D:
print("D")