【问题标题】:Python - switch alternative for non-discrete comparisonsPython - 非离散比较的切换替代方案
【发布时间】:2012-07-19 15:14:21
【问题描述】:

也许以前有人问过这个问题,但我找不到。 我正在尝试实现一些东西来确定给定值的范围。在这个例子中,x 可以是任何实数。

def f(x):
    if x < 0.1:
        do_something_1()
    elif 0.1 <= x < 1:
        do_something_2()
    elif 1 <= x < 10:
        do_something_3()
    elif x >= 10:
        do_something_4()

...你明白了。

我见过很多用字典替换 Python 中的 switch 语句的例子,但我一直将字典理解为索引离散值。

我很难相信 if-elif-else 链是这种情况下的最佳解决方案。有谁知道更好的吗?

【问题讨论】:

  • 我真的不明白 C 的 switch 语句会如何改进这段代码。你能启发我吗?
  • 什么方面的最佳解决方案?速度 ?可读性? ...
  • 我不是一个经验丰富的 C 专家,但你不能做,例如,case 0.1 &lt;= x &lt; 1?我知道打字少了很多,但我觉得代码的意图更清晰。也许我误解了switch 的工作原理。
  • @poorsod:不,你不能。即使可以,case 0.1 &lt;= x &lt; 1elif 0.1 &lt;= x &lt; 1 好多少?
  • -1 这并不真正构成一个问题。投票结束。

标签: python dictionary switch-statement


【解决方案1】:

改善这一点的一个简单方法是不要重复下限。你的代码相当于

if x < 0.1:
    do_something_1()
elif x < 1:
    do_something_2()
elif x < 10:
    do_something_3()
else:
    do_something_4()

如果值真的很多,你可能想bisect,但只有四个选项,上面的代码可能是最好的解决方案,至少在可读性和速度方面。

【讨论】:

  • 上面的例子只是一个例子;我需要分成 26 个范围!我不想让任何阅读代码的人不得不费力通过 26 elifs。
  • @poorsod:不同的解决方案适用于不同的制度,因为它们的规模不同。如果你给出一个简短的例子——这很好,顺便说一句! -- 那么也请提及您的实际问题所涉及的尺寸。
  • @poorsod:这 26 个范围有规律吗?或者它们是由任意常数定义的?如果是前者,使用模式来简化代码。如果是后者,请使用bisect
  • !!那你为什么不只使用val = bisect.bisect_left(x, boundaries) 而不是为每个运行单独的代码呢?
  • 不客气。请注意,即使您没有听说过 bisect,这也最好在边界上的 for 循环中解决,将每个与 x 进行比较并跟踪索引,而不是 26 子句 if/elif 语句。这是XY problem 的一个很好的例子。干杯!
【解决方案2】:

使用bisect包找到值所在的索引,然后调用相应的函数。在您的示例中:

import bisect

def f(x):
    funcs = [do_something_1, do_something_2, do_something_3, do_something_4]
    funcs[bisect.bisect_left([.1, 1, 10], x)]()

【讨论】:

  • 谢谢!我不知道bisect
【解决方案3】:

这是另一种方法,使用 dict 和 for 循环:

ranges_dict = {
    0.1: do_something1,
    1.0: do_something2,
    10.0: do_something3,
    }

for range_val, do_function in sorted(ranges_dict.items()):
    if x < range_val:
        do_function()
        break
else:
    do_something_else()

【讨论】:

    猜你喜欢
    • 2020-05-29
    • 2012-02-29
    • 2017-07-18
    • 2016-10-29
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多