简体   繁体   English

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

[英]Can one use closures to simplify functions in Python?

Imagine if you want to make a closure function that decides some option for what its inner function does. 想象一下,如果你想创建一个闭包函数来决定它的内部函数做什么的一些选项。 In this example, we have an inner function that decides whether a number is even, but the generator decides whether the number zero is even, as if there were a debate. 在这个例子中,我们有一个内部函数来决定一个数是否是偶数,但是生成器决定数字是否是偶数,好像有争论一样。

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

If is_even(x) is run millions of times, it appears reject_zero will still be checked every single time is_even(x) is run! 如果is_even(x)运行数百万次,则每次运行is_even(x)时仍会检查reject_zero! My actual code has many similar 'options' to create a function that is run millions of times, and it would be inconvenient to write functions for every combination of options. 我的实际代码有许多类似的“选项”来创建一个运行数百万次的函数,并且为每个选项组合编写函数会很不方便。 Is there a way to prevent this inefficiency, or does some implementation of Python simplify this? 有没有办法防止这种低效率,或者Python的某些实现是否简化了这一点?

You seem to be looking for something like macros in C. Unfortunately, Python is not compiled (not the same way as C, for purists), and I don't see direct solutions for your need. 你似乎在寻找像C中的宏一样的东西。不幸的是,Python没有被编译(与纯粹主义者的C不同),我没有看到直接的解决方案来满足你的需求。

Still, you could set all your parameters at the beginning of runtime, and select the functions at this moment according to the values of the parameters. 您仍然可以在运行时开始设置所有参数,并根据参数值选择此时的功能。 For instance, your function generator would be something like: 例如,您的函数生成器将类似于:

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)

The backlash of this is having to write a generator for each function that handles such a parameter. 这种情况的强烈反应是必须为处理这种参数的每个函数编写一个生成器。 In the case you present, this is not a big problem, because there are only two versions of the function, that are not very long. 在你提出的情况下,这不是一个大问题,因为只有两个版本的函数,不是很长。

You need to ask yourself when it is useful to do so. 你需要问问自己什么时候这样做有用。 In your situation, there is only one boolean comparison, which is not really resource-consuming, but there might be situations where generating the functions before could become worthwhile. 在您的情况下,只有一个布尔比较,这不是真正的资源消耗,但可能存在以前生成函数可能变得有价值的情况。

consider caching all your options in a list, and the generated function only iterates the chosen function 考虑在列表中缓存所有选项,生成的函数只迭代所选的函数

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

then you could use 然后你可以使用

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

if you need add options then add it to the options dict , and you could usee new_option=True is the generate_is_even function to enable it 如果你需要添加选项然后将它添加到选项dict ,你可以使用new_option=True是generate_is_even函数来启用它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM