在Python中完成此控制流程的最优雅方法是什么?

时间:2017-09-04 01:36:35

标签: python

这里的新编码器;对不起,如果这个问题非常基本。

假设我有这样的功能:

def foo(a=True, b=False):
    for i in range(1000000000):
        if a:
            obfuscate()
        if b:
            frobnicate()

这显然是低效的,因为我通过for循环评估每次迭代的if语句条件。什么是更优雅的方式来完成同样的事情?

编辑:当我试图最小化我的例子时,我认为我掩盖了过多的细节。我没有在这里捕获多个相互依赖关系。任何尚未参与讨论的人都应该明确指出。

5 个答案:

答案 0 :(得分:1)

查看您的代码,您并不表示ab曾发生变化。因此,您可以在开始循环之前确定要调用哪些函数:

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 ...

答案 1 :(得分:0)

我将假设在每次迭代中都会出现a或b,在这种情况下,用if b:替换elif b:。这样,如果是a,则不检查b。

答案 2 :(得分:0)

我不会发现您编写的代码效率低下。此运行时为O(n),适用于您必须浏览列表的大多数情况。但是,有一项建议是,在检查elif是否符合i的情况时,您应该使用b。如下:

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)

答案 3 :(得分:0)

假设语义是正确的(我不知道&#34; *事物&#34;是否有任何副作用或没有,也不知道是否有任何类型的数据依赖),那么你可以移动{{ 1}}(循环不变)在循环之外

if

一般来说,编译器擅长在循环外移动循环不变量。

由于您使用的是python,我认为性能不是您的首要任务,因此我建议您坚持使用更具可读性的初始版本,并让编译器/解释器发挥其魔力并优化此功能对你而言。

答案 4 :(得分:-2)

你可能想要使用elif而不是第二个if if else中的条件仅在a为false时执行。除了代码优化之外,通常还要处理循环运行时的优化。如果条件对优化没有那么大的影响。

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>