Python速度测试——为什么一个异常故障要花费这么多时间

Python速度测试——为什么一个异常故障要花费这么多时间,python,Python,对于“尝试从列表中删除x”的简单操作,我假设“尝试/例外”工作流比“如果/然后”工作流要快。在下面的示例中,except失败(x不在列表中)花费的时间比权限请求(如果x在列表中)多,即使出现异常的可能性为16.6%。为什么? 以下是我编写的测试及其结果: import random, time, timeit class Timer(object): def __enter__(self): self.start = time.time() return

对于“尝试从列表中删除x”的简单操作,我假设“尝试/例外”工作流比“如果/然后”工作流要快。在下面的示例中,except失败(x不在列表中)花费的时间比权限请求(如果x在列表中)多,即使出现异常的可能性为16.6%。为什么?

以下是我编写的测试及其结果:

import random, time, timeit

class Timer(object):
    def __enter__(self):
        self.start = time.time()
        return self

    def __exit__(self, *args):
        self.end = time.time()
        self.secs = self.end - self.start
        self.msecs = self.secs * 1000  # millisecs

def a_function():
    a_list = list(xrange(10))
    choice_list = list(xrange(12))
    choice = random.choice(choice_list)
    try:
        a_list.remove(choice)

    except ValueError:
        pass

def b_function():
    a_list = list(xrange(10))
    choice_list = list(xrange(12))
    choice = random.choice(choice_list)
    if choice in a_list:
        a_list.remove(choice)

with Timer() as a:
    print('test_a', timeit.timeit("a_function()", number=10000, setup="from __main__ import a_function"))

with Timer() as b:
    print('test_b', timeit.timeit("b_function()", number=10000, setup="from __main__ import b_function"))
结果是:

1次尝试:('test_a',0.029724836349487305)('test_b',0.0270681381225594)

2次尝试:('test_a',0.02960801124572754)('test_b',0.026785850524902344)

3次尝试:('test_a',0.0296549705810547)('test_b',0.02665996551513672)


此外,如果我将choice_列表范围增加到20,则差异会扩大,因为异常会更频繁地发生。如果python强烈要求宽恕而不是许可,为什么失败似乎要花费大量时间?

异常在任何语言中都非常昂贵,这是对它们的滥用

异常是指代码无法解释并且在正常操作过程中不会出现的异常情况。不同的语言对什么是例外有不同的规则,但是16%的时间发生的事情不是例外,只是不寻常


异常代价高昂,因为它们涉及堆栈展开和跳转、暂停正常处理以及搜索处理程序。If/then是一个标准的、正常的、有效且清晰的条件

异常在任何语言中都非常昂贵,这是对它们的滥用

异常是指代码无法解释并且在正常操作过程中不会出现的异常情况。不同的语言对什么是例外有不同的规则,但是16%的时间发生的事情不是例外,只是不寻常


异常代价高昂,因为它们涉及堆栈展开和跳转、暂停正常处理以及搜索处理程序。If/then是一个标准的、正常的、有效且清晰的条件

这完全是瞎猜,但可能是因为异常处理基于类,而if/then则纯粹基于逻辑。因此,解释器可以优化简单的条件处理,而不是类流


这是一个彻头彻尾的秘密,但可能是由于异常处理是基于类的,而if/then是纯粹基于逻辑的。因此,解释器可以优化简单的条件处理,而不是类流


Try/catch-by-demancess必须包含与if/then相同的构造(条件跳转)。因为它必须处理更多的事情(比如返回错误),try/catch必然比您自己做测试慢。那
Timer
context manager做什么?这似乎是死代码,而你已经在起诉
timeit
。@delnan计时器可能是我第一次启动速度测试代码时的问题。我通常只需编写函数。Try/catch必须包含与if/then相同的构造(条件跳转)。因为它必须处理更多的事情(比如返回错误),try/catch必然比您自己做测试慢。那
Timer
context manager做什么?这似乎是死代码,而你已经在起诉
timeit
。@delnan计时器可能是我第一次启动速度测试代码时的问题。我通常所做的只是编写函数。虽然我原则上同意您的意见,但在Python中,强烈鼓励用户使用
try…除了在许多情况下使用
if…then
构造之外,其他语言都会使用
if…then子句。虽然计算效率不高,但使用异常向调用堆栈上传递某些类型的消息在语义上是有效的(在Python中)。这一点尤其正确,因为Python中鼓励使用“duck-typing”范式。@JoelCornett:有趣。我对Python知之甚少(我是一个喜欢Ruby的人)。在Ruby中,我们有一个特殊的异常结构,它实际上被命名为throw和catch。例外是为真正例外的人保留的(另一个例子是Obj-C)。显然,OP对效率感兴趣,另外,
try…除了在OP的示例中,似乎对代码的语义没有任何有用的贡献。@doctorlove:这很有趣。谢谢虽然我原则上同意您的看法,但在Python中,强烈鼓励用户使用
try…但在许多情况下,其他语言会使用
if…then
子句。虽然计算效率不高,但使用异常向调用堆栈上传递某些类型的消息在语义上是有效的(在Python中)。这一点尤其正确,因为Python中鼓励使用“duck-typing”范式。@JoelCornett:有趣。我对Python知之甚少(我是一个喜欢Ruby的人)。在Ruby中,我们有一个特殊的异常结构,它实际上被命名为throw和catch。例外是为真正例外的人保留的(另一个例子是Obj-C)。显然,OP对效率感兴趣,另外,
try…除了在OP的示例中,似乎对代码的语义没有任何有用的贡献。@doctorlove:这很有趣。谢谢CPython不进行此类优化。CPython不进行此类优化。