“raise exception()”和“raise exception”(不带括号)有区别吗?

134

定义一个无参数的异常:

class MyException(Exception):
    pass

当提出时,以下两种情况有何不同:

raise MyException

raise MyException()
我找不到任何信息;这是否仅仅是一种过载的语法?

1
阅读此答案:https://dev59.com/jWcs5IYBdhLWcg3wMxFF - satoru
2
严格来说,这不是语法上的问题。在运行时,Python 无法知道它将获得一个类还是一个实例。 - asmeurer
3个回答

144

简而言之,raise MyExceptionraise MyException()都会执行相同的操作。第一种形式会自动实例化您的异常。

来自文档的相关部分如下:

raise将第一个表达式作为异常对象进行评估。它必须是BaseException的子类或实例。如果它是一个类,则在需要时通过使用不带参数的类实例化来获取异常实例。

话虽如此,即使语义相同,第一种形式也微观地更快,而第二种形式更灵活(因为您可以传递参数,如果需要)。

Python中大多数人(即在标准库、常用应用程序和许多书籍中)使用的惯用风格是在没有参数时使用raise MyException。只有在需要传递某些参数时,人们才直接实例化异常。例如:raise KeyError(badkey)


21
为什么第一个形式(不带括号)会微观上更快? - jamesdlin
27
因为自动实例化的 C 代码没有解释器开销,而这个开销会在你自己调用时产生。 - Raymond Hettinger

5

1
值得注意的是,Python 3中raise的语法已经有些改变。但对于这个问题相关的部分仍然是一样的(raise ExceptionType仍会通过调用其构造函数而创建该类型的一个实例,且不带任何参数)。 - Blckknght

-1

是的,ValueErrorValueError()之间有区别。

ValueError是一个类,而ValueError()创建了一个类的实例。这就是为什么type(ValueError) is typetype(ValueError()) is ValueError的原因。

raise的唯一目的是引发异常,

当我们使用ValueError时,将调用类,从而运行构造函数ValueError()

当我们使用ValueError()时,直接调用方法ValueError()

注意:raise ValueError # 简写为 'raise ValueError()'


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接