什么';用Python实现这个控制流最优雅的方法是什么?
这里的新编码员;抱歉,如果这个问题非常基本 假设我有这样一个函数:什么';用Python实现这个控制流最优雅的方法是什么?,python,Python,这里的新编码员;抱歉,如果这个问题非常基本 假设我有这样一个函数: def foo(a=True, b=False): for i in range(1000000000): if a: obfuscate() if b: frobnicate() 这显然是低效的,因为我在通过for循环的每次迭代中计算if语句条件。完成同样的事情,还有什么更优雅的方式 编辑:我认为当我试图最小化我的例子时,我掩盖了太多的细
def foo(a=True, b=False):
for i in range(1000000000):
if a:
obfuscate()
if b:
frobnicate()
这显然是低效的,因为我在通过for循环的每次迭代中计算if语句条件。完成同样的事情,还有什么更优雅的方式
编辑:我认为当我试图最小化我的例子时,我掩盖了太多的细节。我在这里没有捕捉到多个相互依赖关系。任何尚未参与讨论的人都应该避开。我假设每次迭代都会出现a或b,在这种情况下,如果b:替换为
elif b:
。这样,如果它是a,它就不会检查b。我看不出您编写的代码有任何低效之处。此运行时是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>
假设语义正常(我不知道“*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>
def foo(a,b):
对于范围(1000)内的i:
如果是:
对于范围(1000)内的i:
如果b:
对于范围(1000)内的i:
一般来说,编译器擅长将循环不变量移到循环外
由于您使用的是python,我想性能不是您的首要任务,因此我建议您坚持使用更具可读性的初始版本,让编译器/解释器发挥他们的魔力,并在幕后为您优化它。您可能希望使用elif而不是第二个if,因为else中的条件仅在a为false时执行。除此之外,代码优化通常涉及运行时循环的优化。如果条件对优化没有这么大的影响
def foo(a=True, b=False):
for i in range(1000000):
if a:
obfuscate()
elif b:
frobnicate()
查看您的代码,您不会表示
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和b
情况拆分为单独的代码行,只调用这两个函数,为您节省一些操作码以进行调用:
if a and b:
for i in range(1000000):
obfuscate()
frobnicate()
return
elif ...
a
和b
是向量吗?你的例子不清楚。这完全取决于。。。评估if
条件的成本很小。这不是你应该指导你的优化工作的地方。每次做的事情都是一样的,还是它在某种程度上使用了i
?我为这个糟糕的例子道歉。我现在要回去编辑它。我为没有在原始示例(我已经编辑过)中明确表示歉意。a和b是此函数的参数;在for循环的每次迭代中,它们始终具有相同的值。我确实理解elif减少了计算开销,但我认为它会给示例增加不必要的复杂性我修改了我的答案。这回答了你的问题吗?是的,我知道。我显然应该这样写我的例子,因为这是大多数人都抓住的,这将取决于变量。例如,CPython甚至不能进行拼写优化。代码比这复杂得多。我想我在尽量减少我的例子的过程中丢失了一些重要的细节。函数实际上传递了一个对象列表,并在列表不为空时运行while循环来执行一系列操作。在通过while循环的每次迭代中,它都会从列表中弹出一些对象,执行一些复杂的操作,然后根据布尔参数a和b的真/假值(在函数中不会改变)决定运行它们的类方法中的哪一个。有问题的函数被调用了很多次,足够运行我的程序需要几分钟。当我在最初的示例中使用1000时,人们告诉我优化if语句不值得我花时间。我试图强调这可能值得我花时间,但我不想写一个荒谬的长数字。10^6似乎是个不错的折衷方案。我想你的意思是“很多”,这很好。具有讽刺意味的是,人们会说“提供一个最小的示例”,然后说“那个代码很琐碎!”;-)@AustinHastings这不是代码的琐碎。如果您有一个运行数百万次的循环,那么If子句可能是您最不应该优化的内容。此外,值得指出的是,如果混淆
或frobnite
操作非常重要,那么此函数可能不是您的瓶颈。重新构造后,搜索“profiling”python。有一些模块可以帮助你找出你的时间花在哪里。@ayhan完全公平。不过,我仍在寻找这个问题的答案。我觉得这是一件我应该不费吹灰之力就能完成的事情,但我不知道如何正确地完成它。
if a and b:
for i in range(1000000):
obfuscate()
frobnicate()
return
elif ...