python - python 闭包中的条件性能

标签 python performance functional-programming closures

在下面的代码示例中,我有两个更高级别的函数 factory1factory2 ,它们生成具有相同行为的函数。第一个工厂 factory1 通过让返回的函数根据工厂的 bool 值更改行为,避免显式定义两个不同的函数。在此示例中,此功能的用处并不那么明显,但如果要生成的函数更复杂,则显式写出该函数的两个几乎相同的副本(如 factory2 中所做的那样)将不利于可读性和可维护性.

但是,从计时结果可以看出,factory2 的实现速度更快。

有没有办法在不显式定义两个替代函数的情况下实现 factory2 的性能?

def factory1(condition):

    def fn():
        if condition:
            return "foo"
        else:
            return "bar"

    return fn


def factory2(condition):

    def foo_fn():
        return "foo"

    def bar_fn():
        return "bar"

    if condition:
        return foo_fn
    else:
        return bar_fn


def test1():
    fn = factory1(True)
    for _ in range(1000):
        fn()


def test2():
    fn = factory2(True)
    for _ in range(1000):
        fn()


if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test1()", setup="from __main__ import test1"))
    # >>> 62.458039999
    print(timeit.timeit("test2()", setup="from __main__ import test2"))
    # >>> 49.203676939

编辑:更多上下文

我问的原因是我正在尝试生成一个看起来像这样的函数:

def function(data):
    data = some_transform(data)

    if condition:
        # condition should be considered invariant at time of definition
        data = transform1(data)
    else:
        data = transform2(data)

    data = yet_another_transform(data)

    return data

最佳答案

根据“显式定义两个函数”的含义,请注意,在检查条件之前,您不必执行 def 语句:

def factory3(condition):

    if condition:
        def fn():
            return "foo"
    else:
        def fn():
            return "bar"

    return fn

有人可能会反对,在确定运行时使用哪一个来定义函数之前,仍然必须编译两个代码对象。在这种情况下,您可能会在动态构造的字符串上使用 exec注意 对于除了我将在此处展示的静态示例之外的任何内容,都需要仔细完成此操作。请参阅the old definition for namedtuple一个很好的(?)例子。

def factory4(condition):
    code = """def fn():\n    return "{}"\n""".format("foo" if condition else "bar")
    exec(code)
    return fn

更安全的替代方案可能是使用闭包:

def factory5(condition):
    def make_fun(val):
        def _():
            return val
        return _
    if condition:
        return make_fun("foo")
    else:
        return make_fun("bar")

make_fun 也可以在 factory5 外部定义,因为它根本不依赖于condition


根据您的编辑,我认为您只是想实现依赖项注入(inject)。不要在函数中放置 if 语句;传递 transform1transform2 作为参数:

def function(transform):
    def _(data):
        data = some_transform(data)
        data = transform(data)
        data = yet_another_transform(data)
        return data
    return _

if condition:
    thing = function(transform1)
else:
    thing = function(transform2)

关于python - python 闭包中的条件性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56582050/

相关文章:

performance - CUDA:内核性能对占用的依赖性

Swift Final 类和函数

javascript - 了解递归函数的蹦床优化

java - 潜在无限流的功能解压缩实现

python - Pandas 过滤连续的行

python - 如何使用pygame模块?

python - 使用相同来源的余弦相似度和完全不同的结果

javascript - 双函数调用或将结果存储为变量?

.net - 是否可以在F#中执行函数重载?

python - 在 numpy 数组中插入 NaN 值