什么';用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 ...