alr*_*lta 12 python match switch-statement python-3.x
我期望 Python match/case对每个案例有相同的时间访问权限,但似乎我错了。有什么好的解释为什么吗?
让我们使用以下示例:
def match_case(decimal):
match decimal:
case '0':
return "000"
case '1':
return "001"
case '2':
return "010"
case '3':
return "011"
case '4':
return "100"
case '5':
return "101"
case '6':
return "110"
case '7':
return "111"
case _:
return "NA"
Run Code Online (Sandbox Code Playgroud)
并定义一个快速工具来测量时间:
import time
def measure_time(funcion):
def measured_function(*args, **kwargs):
init = time.time()
c = funcion(*args, **kwargs)
print(f"Input: {args[1]} Time: {time.time() - init}")
return c
return measured_function
@measure_time
def repeat(function, input):
return [function(input) for i in range(10000000)]
Run Code Online (Sandbox Code Playgroud)
如果我们每次运行10000000每种情况,时间如下:
for i in range(8):
repeat(match_case, str(i))
# Input: 0 Time: 2.458001136779785
# Input: 1 Time: 2.36093807220459
# Input: 2 Time: 2.6832823753356934
# Input: 3 Time: 2.9995620250701904
# Input: 4 Time: 3.5054492950439453
# Input: 5 Time: 3.815168857574463
# Input: 6 Time: 4.164452791213989
# Input: 7 Time: 4.857251167297363
Run Code Online (Sandbox Code Playgroud)
只是想知道为什么访问时间不同。这不是通过查找表进行优化的吗?请注意,我对具有相等访问时间的其他方式(即使用字典)不感兴趣。
Nic*_*ert 13
我参加聚会迟到了,但我觉得我可以在这个帖子中添加一些有用的东西。
不久前,我在 Medium 上发表了一篇关于 Python 的匹配情况性能的文章,分析了生成的字节代码并执行基准测试和比较。如果您愿意,可以在这里阅读这篇文章。我认为这是值得你花时间的。
不过,我还是要在这里总结一下。
许多编程语言将它们的 switch-case 语句实现为 if-else 序列。有时,可以将 switch-case 优化为高效的查找表,但情况并非总是如此。
在 Python 中,这种优化永远不会执行,因此总是会导致一系列条件检查。
从文章中可以看出 if-else 和 match-case 之间的速度比较:
Average time for match_case: 0.00424 seconds
Average time for if_else: 0.00413 seconds
Run Code Online (Sandbox Code Playgroud)
如您所见,它们几乎相等。
另外,如果您反汇编这两个语句,您会发现它们生成几乎相同的字节代码。
只是需要指出的一个区别是,if-else 检查调用对象的__eq__()方法,而 match-case 在内部进行比较。
最后,这是一个还包括哈希表(字典)的基准测试:
Average time for match_case: 0.00438 seconds
Average time for if_else: 0.00433 seconds
Average time for dict_lookup: 0.00083 seconds
Run Code Online (Sandbox Code Playgroud)
因此,如果您热衷于性能,则应该使用哈希表。尽管 match-case 类似于 C 风格的 switch-case,但事实并非如此:match-case 旨在用于结构模式匹配,而不是用于替换高性能哈希表和查找表。
与传统的 if-elif-else 链相比, PEP 622中引入的 match/case 语句提供了一种更优雅、更易读的模式匹配方法。它的主要优点在于能够简化复杂的条件逻辑。
def is_tuple(node):
if isinstance(node, Node) and node.children == [LParen(), RParen()]:
return True
return (isinstance(node, Node)
and len(node.children) == 3
and isinstance(node.children[0], Leaf)
and isinstance(node.children[1], Node)
and isinstance(node.children[2], Leaf)
and node.children[0].value == "("
and node.children[2].value == ")")
Run Code Online (Sandbox Code Playgroud)
def is_tuple(node: Node) -> bool:
match node:
case Node(children=[LParen(), RParen()]):
return True
case Node(children=[Leaf(value="("), Node(), Leaf(value=")")]):
return True
case _:
return False
Run Code Online (Sandbox Code Playgroud)
虽然在最原始的情况下它可能相当于字典查找,但通常情况并非如此。案例模式的设计看起来像普通的 python 代码,但实际上它们隐藏isinstance并len调用,并且不会执行当您看到类似Node().
本质上,这相当于一系列 if ... elif ... else 语句。请注意,与之前提出的 switch 语句不同,预先计算的调度字典语义在这里不适用。
| 归档时间: |
|
| 查看次数: |
9040 次 |
| 最近记录: |