有没有更有效的编写合并函数的方法?

时间:2019-05-08 19:19:15

标签: python python-3.x performance null coalesce

浏览一些代码后,发现以下功能:

def coalesce(*args, null=None):
    return next((obj for obj in args if obj is not null and obj != null), null)

是否有更有效的方法来运行此操作,或者以更Python化的方式思考问题?

第一个尝试的替代方法如下:

def coalesce(*args):
    return next(filter(None, args), None)

这是尝试过的第二种选择:

def coalesce(*args, null=None):
    return next(itertools.filterfalse(functools.partial(operator.eq, null), args), null)

这是我想到的第三个选择:

def coalesce(*args):
    return next((obj for obj in args if obj is not None), None)

写了第四种替代方法,希望用C编写的代码更快:

def coalesce(*args):
    return next(itertools.filterfalse(functools.partial(operator.is_, None), args), None)

使用timeit,三个不同功能的计时结果为:

  • 0.7040689999994356
  • 0.3396129999891855
  • 0.8870604000112507
  • 0.5313313000078779
  • 0.8086609000019962

这似乎表明第二个函数是更可取的,但是并不能回答哪个是最Pythonic的问题。

1 个答案:

答案 0 :(得分:2)

您考虑过

def coalesce4(*args):
    for x in args:
        if x is not None:
            return x

这比问题中显示的三个功能要快得多:

In [2]: import tmp

In [3]: %timeit tmp.coalesce1(None, None, 1)
782 ns ± 1.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [4]: %timeit tmp.coalesce2(None, None, 1)
413 ns ± 8.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [5]: %timeit tmp.coalesce3(None, None, 1)
678 ns ± 0.782 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [6]: %timeit tmp.coalesce4(None, None, 1)
280 ns ± 0.218 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

在Python 3.8中,您可以选择

def coalesce5(*args):
    if any(rv := x for x in args if x is not None):
         return rv

实际上与第三个选项相同,并且类似功能的运行时间表明它的速度大致相同(〜680 ns)。