Python if else 微优化

发布于 2024-08-15 13:16:38 字数 200 浏览 4 评论 0原文

在思考代码优化时,我想知道 python 中哪个更昂贵:

if x:
    d = 1
else:
    d = 2

或者

d = 2
if x:
    d = 1

有什么想法吗?我喜欢第二次减少的行数,但想知道重新分配是否比条件切换成本更高。

In pondering optimization of code, I was wondering which was more expensive in python:

if x:
    d = 1
else:
    d = 2

or

d = 2
if x:
    d = 1

Any thoughts? I like the reduced line count in the second but wondered if reassignment was more costly than the condition switching.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

银河中√捞星星 2024-08-22 13:16:38

不要思考,不要怀疑,测量——使用 timeit 在 shell 命令行(迄今为止最好、最简单的方法使用它!)。笔记本电脑上 Mac OSX 10.5 上的 Python 2.5.4...:

$ python -mtimeit -s'x=0' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0748 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0685 usec per loop
$ python -mtimeit -s'x=0' 'd=2' 'if x: d=1'
10000000 loops, best of 3: 0.0734 usec per loop
$ python -mtimeit -s'x=1' 'd=2' 'if x: d=1'
10000000 loops, best of 3: 0.101 usec per loop

所以你看:与“if/其他”形式;因此,在微优化环境中,只有当 x 为假的可能性是 true 的 30 倍或左右时,才应使用前者。另外:

$ python -mtimeit -s'x=0' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0736 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.076 usec per loop

... if/else 的三元运算符有其自己的微小优点和缺点。

当差异如此之小时,您应该重复测量,确定噪声水平,并确保您不会将“噪声”中的差异视为显着。例如,要在“x 为真”情况下比较语句与表达式 if/else,请重复几次:

$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.076 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0749 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0742 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0749 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0745 usec per loop

现在您可以声明表达式形式需要(在本机和关键软件版本上)74.2 到 76.0 纳秒 - - 该范围比任何单个数字更具表现力。类似地:

$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0688 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0681 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0687 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0679 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0692 usec per loop

现在您可以自信地声明语句形式(在相同条件下)需要 67.9 到 69.2 纳秒;因此,对于 x true,对于表达式形式,它的优点是 4.8 到 8.1 纳秒(将后一个间隔估计限制为 6.3 到 6.8 纳秒是相当公平的,比较 min/min 和 max/max 而不是 min/max 和 max/ min 作为更广泛、更审慎的估计)。

当然,一旦您意识到任何给定的护理都是微观的,那么值得投入多少时间和精力来研究这些微观差异,这是一个不同的问题。

Don't ponder, don't wonder, measure -- with timeit at the shell command line (by far the best, simplest way to use it!). Python 2.5.4 on Mac OSX 10.5 on a laptop...:

$ python -mtimeit -s'x=0' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0748 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0685 usec per loop
$ python -mtimeit -s'x=0' 'd=2' 'if x: d=1'
10000000 loops, best of 3: 0.0734 usec per loop
$ python -mtimeit -s'x=1' 'd=2' 'if x: d=1'
10000000 loops, best of 3: 0.101 usec per loop

so you see: the "just-if" form can save 1.4 nanoseconds when x is false, but costs 40.2 nanoseconds when x is true, compared with the "if/else" form; so, in a micro-optimization context, you should use the former only if x is 30 times more likely to be false than true, or thereabouts. Also:

$ python -mtimeit -s'x=0' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0736 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.076 usec per loop

...the ternary operator of the if/else has its own miniscule pluses and minuses.

When the differences are as tiny as this, you should measure repeatedly, establish what the noise level is, and ensure you're not taking differences "in the noise" as significant. For example, to compare statement vs expression if/else in the "x is true" case, repeat each a few times:

$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.076 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0749 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0742 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0749 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0745 usec per loop

now you can state that the expression forms takes (on this machine and versions of key software) 74.2 to 76.0 nanoseconds -- the range is much more expressive than any single number would be. And similarly:

$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0688 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0681 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0687 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0679 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0692 usec per loop

now you can state confidently that the statement form takes (under identical conditions) 67.9 to 69.2 nanoseconds; so its advantage, for x true, wrt the expression form, is 4.8 to 8.1 nanoseconds (it's quite fair to restrict this latter interval estimation to 6.3 to 6.8 nanoseconds, comparing min/min and max/max instead of min/max and max/min as the wider, more prudential estimate does).

How much time and energy is worth devoting to such microscopic differences, once you've realized for any given care that they are microscopic, is, of course, a different issue.

﹏雨一样淡蓝的深情 2024-08-22 13:16:38

您可能应该对此进行基准测试,但还有第三种形式使用三元运算符:

d = 1 if x else 2

You should probably benchmark this, but there's also a third form that uses the ternary operator:

d = 1 if x else 2
私野 2024-08-22 13:16:38

第二个显然应该更昂贵,如果x为假,它执行相同的操作,如果x为真,则执行两倍的赋值。

假设:在Python中赋值比条件跳转更昂贵,这是有道理的,因为它被解释并且它必须读取运行时哈希来获取新值,然后将其上传到相同的哈希中。

The second one should obviously be more expensive, it does the same operations if x is false and twice the assignments if x is true.

Assumption: assignment is more expensive in python than a conditional jump, which makes sense since its interpreted and it has to read a run time hash to get the new value then upload it in the same hash.

兲鉂ぱ嘚淚 2024-08-22 13:16:38

我认为最具可读性的就是最优化的(至少在可读性方面)。

if...else 结构清楚地表明您正在处理非此即彼的情况。

如果 (d==2) 是通常的值并且您的 if 测试不寻常的情况,则赋值构造可能更有意义。如果你的赋值从 if 中移开,这个结构就会变得不太清晰。

在这个简单的例子中,这并不重要。对于更复杂的代码,我几乎总是会优化可读性,即使会牺牲一些 CPU 周期。

I would argue that the one that is most readable is the most optimized (for readability at least).

The if...else construct makes it clear that you are dealing with an either/or case.

The assignment construct might make more sense if (d==2) is the usual value and your if tests for an unusual case. This construct becomes less clear if your assignment gets moved away from the if.

In this simple example it doesn't really matter. For more complex code, I would almost always optimize for readability, even at the expense of a few CPU cycles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文