Min Max 类函数,使用 if best == None 和 Python 循环内的条件
Min Max like function, using if best == None with the condition inside the loop in Python
在我们需要根据条件搜索最佳元素的函数中(例如 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,我不知道编译器是否优化了它。
为了查看此示例的执行时间是否相似,我计算了方法 A 和 B 的时间
nb = 100000000 # 100_000_000
list_vals = random.sample(range(nb), nb)
- 时间(A) = 24.00 秒
- 时间(B) = 19.31 秒
我用其他长度重复了测试,结果是一样的,B方法比A方法分析(相对)快。
感谢您的帮助。
编辑一:假设 list_vals 不为空。谢谢@0x5453
在通用代码中,您可能希望使用任意可迭代对象,而不仅仅是 list
,在这种情况下,只有第一种形式有效(您无法索引 non-sequences)。您可能还需要处理可能为空的输入(A 通过生成 None
来处理它们,而 B 引发 IndexError
)。它确实增加了 non-zero 成本(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:]
可以做到),您不必发明一个哨兵初始情况的值,因为您可以安全地获取第一个元素一次,并且您不会针对自身测试初始值(因为有状态迭代器只产生一次初始值)。
在我们需要根据条件搜索最佳元素的函数中(例如 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,我不知道编译器是否优化了它。
为了查看此示例的执行时间是否相似,我计算了方法 A 和 B 的时间
nb = 100000000 # 100_000_000
list_vals = random.sample(range(nb), nb)
- 时间(A) = 24.00 秒
- 时间(B) = 19.31 秒
我用其他长度重复了测试,结果是一样的,B方法比A方法分析(相对)快。
感谢您的帮助。
编辑一:假设 list_vals 不为空。谢谢@0x5453
在通用代码中,您可能希望使用任意可迭代对象,而不仅仅是 list
,在这种情况下,只有第一种形式有效(您无法索引 non-sequences)。您可能还需要处理可能为空的输入(A 通过生成 None
来处理它们,而 B 引发 IndexError
)。它确实增加了 non-zero 成本(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:]
可以做到),您不必发明一个哨兵初始情况的值,因为您可以安全地获取第一个元素一次,并且您不会针对自身测试初始值(因为有状态迭代器只产生一次初始值)。