python - Repeatedly check conditions inside loop or check up front but have two loops?
问题描述
I have implemented a python function in 2 different ways, as shown below:
1st:
def foo(varA, varB):
if not (varA or varB):
return False
for test1 in test2:
if varA:
# Perform Action A
if varB:
# Perform Action B
return True
2nd:
def foo(varA, varB):
if not (varA or varB):
return False
if varA:
for test1 in test2:
# Perform Action A
if varB:
for test1 in test2:
# Perform Action B
return True
I want to know which method will take less time in execution.
解决方案
这取决于.
这里没有确定的答案。这取决于迭代的成本、迭代的元素数量以及测试布尔值的成本。如果bool(varA)
orbool(varB)
成本高(实现速度慢),那么您希望避免该成本并只循环test2
两次。
但是如果迭代test2
很慢(it = iter(test2)
然后重复调用next(it)
很慢),那么你会想要避免迭代两次。
最后,这里有两个 O(N) 线性算法。哪个更快完全取决于固定成本。您必须对代码进行计时才能知道选择哪一个。确保在不同的场景下多次运行测试,因为两者之间的正态分布是什么很重要,两者之间的正确分布bool(varA)
频率 bool(varB)
是多少?如果其中一个很少是正确的,那可能会对整体执行成本产生影响。
如果我们假设varA
和varB
是同一类型的对象,并且在测试它们的布尔真值的成本上没有差异,那么将其转换为公式,则两个选项的成本可以表示为:
cost_iteration * length * (2 * cost_test)
和
(2 * cost_test) + ((1 + probability_of_both_true) * cost_iteration * length)
其中cost_iteration
是使迭代器前进一步的成本,test2
需要length
迭代的次数,以及确定orcost_test
的布尔值的成本。varA
varB
请注意,我忽略了test2
不是可迭代而是一次性迭代器的可能性。如果test2
是一个迭代器,那么您不能多次循环它,因此您别无选择。
从上面的公式可以看出,即使使用标准的 Python 类型, and 没有自定义__bool__
或__len__
实现,varA
andvarB
没有自定义__iter__
或__getitem__
实现,test2
wheretest2
不是打开的文件对象(I/O 很慢),它仍然取决于两个值都为真的频率。
timeit
使用模块的一些简单的计时测试很容易看到这一点,并且test2 = range(100)
:
>>> import timeit
>>> def option1(a, b):
... if not (a or b): return False
... for _ in test2:
... if a: pass
... if b: pass
...
>>> def option2(a, b):
... if not (a or b): return False
... if a:
... for _ in test2: pass
... if b:
... for _ in test2: pass
...
>>> test2 = range(100)
两个变量都为真:
>>> timeit.timeit("t(True, True)", "from __main__ import option1 as t")
1.917803047000234
>>> timeit.timeit("t(True, True)", "from __main__ import option2 as t")
2.0743740369998704
只有一个变量为真:
>>> timeit.timeit("t(True, False)", "from __main__ import option1 as t")
1.7149272380002003
>>> timeit.timeit("t(True, False)", "from __main__ import option2 as t")
1.095426841000517
timeit.timeit()
默认情况下重新运行测试 100 万次,因此上述时间以每次执行的微秒为单位。
如果两者varA
和varB
主要是正确的,那么第一个选项会稍微快一点。但是,如果只有其中一个是正确的更为常见,那么您需要第二种选择,因为它不必经常测试,因此以显着优势获胜。
如果要迭代的元素更多,时间可能会有所不同test2
,因此您选择哪一个还必须考虑到您的典型迭代计数将是多少。
推荐阅读
- woocommerce - 无法按供应商添加 woocommerce 订单过滤器
- r - 在直方图的背景中添加图像
- java - 无法在 Android 上获得写入权限
- sql - 如何避免多次加入同一张表?
- php - 如何将带有 arc2 的新个人添加到我的 owl 文件中?
- c++ - 将方法应用于以另一个类的对象作为成员的类时出错
- database - 使用 DynamoDB 和 Exactly Once Delivery 进行事件溯源,我应该按 AggregateId 排序吗?
- reactjs - 让消费者呈现提供者的目的是什么?
- iphone - iOS(iphone 和 ipad)拒绝在 HTML 电子邮件中显示日期和时间
- python - 为什么积极的前瞻最终不能与 /$ 一起使用