在此处新的编码器;抱歉,如果这个问题非常基本。
假设我有这样的函数:
def foo(a=True, b=False):
for i in range(1000000000):
if a:
obfuscate()
if b:
frobnicate()
这显然效率低下,因为我通过for循环评估了每次迭代的IF语句条件。什么是完成同一件事的更优雅的方式?
编辑:当我试图最大程度地减少示例时,我认为我掩盖了太多细节。我在这里没有捕捉到多种相互依赖。尚未参与讨论的任何人都应该清除。
查看您的代码,您不会指出a
或b
是否会更改。因此,您可以在开始循环之前确定要调用哪些功能:
def foo(a=True, b=False):
for i in range(1000000):
if a:
obfuscate()
if b:
frobnicate()
变为:
def foo(a=True, b=False):
action = None
if a and b:
def f():
obfuscate()
frobnicate()
action = f
elif a:
action = obfuscate
elif b:
action = frobnicate
else:
return # Loop won't call any functions, skip it.
for i in range(1000000):
action()
我假设通过1000000
,您的意思是"很多次"。(实际上,在现代硬件上不是1M。)如果是的话,您可能需要将a and b
案例分成一个单独的代码行,该行仅调用两个函数,为您节省了一些用于调用的操作码:
if a and b:
for i in range(1000000):
obfuscate()
frobnicate()
return
elif ...
我将假设每次迭代中都会发生A或B,在这种情况下,将if b:
替换为elif b:
。这样,如果是a,它不会检查b。
假设语义是可以的(我不知道"*thing"是否具有任何副作用或否,或者是否存在任何数据依赖性),那么您可以移动循环外的if
(循环不变)
def foo(a, b):
for i in range(1000):
<do things>
if a:
for i in range(1000):
<do something>
if b:
for i in range(1000):
<do something slightly different>
一般而言,编译器擅长在循环外移动循环不变。
由于您使用的是Python,我想性能不是您的首要任务,所以我建议您坚持使用更可读的初始版本,然后让编译器/解释器做他们的魔术并为您优化在引擎盖下。
我看不到您编写的代码效率低下。此运行时为O(n)
,适用于您必须浏览列表的大多数情况。但是,一个建议是,在检查i
是否适合b
的情况下,应该使用elif
。如下:
def foo(a, b):
for i in range(1000):
<do things>
if a:
<do something>
elif b:
<do something slightly different>
编辑:如果A和B是固定参数,则可以使用:
def foo(a, b):
l = [i for i in range(1000)]
if a:
funcA(l)
elif b:
funcB(l)
您可能需要使用elif而不是第二个,而仅当a是false时执行条件。除了优化代码外,还涉及循环运行时的优化。如果条件对优化没有太大影响。
def foo(a=True, b=False):
for i in range(1000000):
if a:
obfuscate()
elif b:
frobnicate()