可以使用闭包来简化Python中的函数吗?

时间:2016-11-14 07:07:53

标签: python closures

想象一下,如果你想创建一个闭包函数来决定它的内部函数做什么的一些选项。在这个例子中,我们有一个内部函数来决定一个数是否是偶数,但是生成器决定数字是否是偶数,就好像存在争论一样。

def generate_is_even(reject_zero):
    def is_even(x):
        return (x % 2 == 0 and x != 0) if reject_zero else x % 2 == 0
    return is_even

如果is_even(x)运行数百万次,则每次运行is_even(x)时仍会检查reject_zero!我的实际代码有许多类似的“选项”来创建一个运行数百万次的函数,并且为每个选项组合编写函数会很不方便。有没有办法防止这种低效率,或者Python的某些实现是否简化了这一点?

2 个答案:

答案 0 :(得分:1)

你似乎在寻找像C中的宏一样的东西。不幸的是,Python没有被编译(与纯粹主义者的C不同),我没有看到直接的解决方案来满足你的需求。

但是,您可以在运行时开始设置所有参数,并根据参数值选择此时的功能。例如,您的函数生成器将类似于:

def generate_is_even(reject_zero):
    def is_even_true(x):
        return (x % 2 == 0 and x != 0)
    def is_even_false(x):
        return x % 2 == 0
    return (is_even_true if reject_zero else is_even_false)

def setup(reject_zero, arg2, arg3):
    is_even = generate_is_even(reject_zero)

这种情况的强烈反应是必须为处理这种参数的每个函数编写一个生成器。在你提出的情况下,这不是一个大问题,因为只有两个版本的函数,不是很长。

你需要问问自己什么时候这样做有用。在您的情况下,只有一个布尔比较,这实际上并不消耗资源,但可能会出现以前生成函数的情况。

答案 1 :(得分:1)

考虑在列表中缓存所有选项,生成的函数只迭代所选函数

xor(A,D)

然后你可以使用

def generate_is_even(**kwargs):
    options = {'reject_zero': lambda x: x != 0}
    enabled = [options[o] for o in options if o in kwargs and kwargs[o]]
    def is_even(x):
        return all([fn(x) for fn in enabled]) and x % 2 == 0
    return is_even

如果您需要添加选项,请将其添加到选项is_even_nozero = generate_is_even(reject_zero=True) is_even_nozero(0) # gives False is_even = generate_is_even() is_even(0) # gives True ,您可以使用dict启用它的generate_is_even函数