类似Min-Max的函数,在Python中使用if best==None和循环内的条件



在我们需要根据条件搜索最佳元素的函数中(如Min-Max函数:搜索最小值或最大值(,我看到一些(或许多(人在条件检查的同时,在循环中检查包含最佳答案的变量是否为None。

为了说明这一点,让以下2个源代码:
A(在循环中使用测试is None

list_vals = [10,9,8,7,6,5,4,3,2,1]
min_val = None
for val in list_vals:
if min_val is None or val<min_val:
min_val = val
print("min = ", min_val)

B( 最佳接收第一元素

list_vals = [10,9,8,7,6,5,4,3,2,1]
min_val = list_val[0]
for val in list_vals:
if val<min_val:
min_val = val
print("min = ", min_val)

我的问题是:

  • 为什么有些人在做第一种形式(A(?这是一个很好的练习吗
  • 如果我们使用第一个from,这意味着在每次迭代中,我们都会检查变量是否为None,我不知道编译器是否对此进行了优化

为了查看这个例子的执行时间是否相似,我用计算了AB两种方法的时间

nb = 100000000 # 100_000_000
list_vals = random.sample(range(nb), nb)
  • 时间(A(=24.00 s
  • 时间(B(=19.31秒

我用其他长度重复了测试,结果是一样的,B方法的分析速度(相对(比A方法快。

谢谢你的帮助。

编辑一个:假设list_vals不为空。谢谢@0x5453

在通用代码中,您可能希望使用任意可迭代项,而不仅仅是list,在这种情况下,只有第一种形式才有效(不能对非序列进行索引(。您可能还需要处理潜在的空输入(A通过生成None来处理它们,而B则引发IndexError(。它确实增加了非零成本(CPython只有最简单、最局部的优化器;它不能像"min_val在第一个循环上只有None"这样进行广泛的推导(。如果性能至关重要,您可以通过以下方式两全其美(尽管代码稍丑(:

vals = ... could be any iterable ...
iter_vals = iter(vals)  # Explicitly convert to iterator (if already an iterator, just returns vals at trivial cost)
min_val = next(iter_vals, None)  # Pulls first value, or None if vals was empty
for val in iter_vals:  # Iterates rest of values looking for minimum
if val < min_val:
min_val = val
print("min = ", min_val)

在这种情况下,您不需要假设输入是一个序列,也不需要对数据进行不必要的复制(切片list_vals[1:]可以做到这一点(,也不必为初始情况创建一个sentinel值,因为您可以安全地获取第一个元素一次,而且不需要对其本身测试初始值(因为有状态迭代器只生成一次初始值(。

相关内容

最新更新