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



在此处新的编码器;抱歉,如果这个问题非常基本。

假设我有这样的函数:

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

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

编辑:当我试图最大程度地减少示例时,我认为我掩盖了太多细节。我在这里没有捕捉到多种相互依赖。尚未参与讨论的任何人都应该清除。

查看您的代码,您不会指出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 ...

我将假设每次迭代中都会发生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()

相关内容

最新更新