创建一些修复了某些变量的函数的副本

时间:2016-08-05 12:06:30

标签: python python-2.7 closures

假设我有一个功能

def multiply_by(x, multiplier):
    return x * multiplier

如何创建该函数的副本并修复该函数中的乘数?

multiply_by_5 = multiply_by?    <-- here I need python magic

这样multiply_by_5只有一个参数x而乘数是5?那么

multiply_by_5(2)
10

Python 2.7中有没有办法做到这一点?

5 个答案:

答案 0 :(得分:3)

您可以将functools.partial与关键字参数一起使用:

>>> def multiply_by(x, multiplier):
...     return x * multiplier
...
>>> from functools import partial
>>> multiply_by_5 = partial(multiply_by, multiplier=5)
>>> multiply_by_5(2)
10

答案 1 :(得分:2)

functools.partial完全是为了这个。

你可以像

一样使用它
import functools
multiply_by_5=functools.partial(multiply_by,multiplier=5)

答案 2 :(得分:2)

根据@ niemmi的answer的建议,functools.partial可能是要走的路。

但是,使用curried函数可以完成类似的工作:

def multiply_by(multiplier):
    def multiply(x):
        return multiplier * x
    return multiply

>>> multiply_by_5 = multiply_by(5)    # no magic
>>> multiply_by_5(2)
10

或者使用lambda语法:

def multiply_by(multiplier):
    return lambda x: multiplier * x

请注意partial更简洁,更高效,更直接以标准方式表达您的意图。上面的技术是一个名为closure的概念的例子,它意味着在内部范围中定义的函数可以引用在封闭范围中定义的变量,并且“关闭”它们,记住它们,甚至改变它们。

由于这种技术更为通用,因此您的代码读者可能需要更多时间来理解您在代码中的确切含义,因为您的代码可能是任意复杂的。

特别是对于乘法(和其他运算符)partial可以与operator.mul结合使用:

>>> import functools, operator
>>> multiply_by_5 = functools.partial(operator.mul, 5)
>>> multiply_by_5(2)
10

答案 3 :(得分:2)

这是一个不使用functools.partial的替代方案。相反,我们在函数内定义一个函数。内在功能&#34;记得&#34;它需要的外部函数的任何局部变量(包括外部函数的参数)。实现这一目标的神奇之处称为closure

def multiply_factory(multiplier):
    def fixed_multiply(x):
        return x * multiplier
    return fixed_multiply

multiply_by_3 = multiply_factory(3)
multiply_by_5 = multiply_factory(5)

for i in range(5):
    print(i, multiply_by_3(i), multiply_by_5(i))

<强>输出

0 0 0
1 3 5
2 6 10
3 9 15
4 12 20

如果需要,可以在闭包中使用现有的multiply_by函数,但由于额外函数调用的开销,效率稍低。例如:

def multiply_factory(multiplier):
    def fixed_multiply(x):
        return multiply_by(x, multiplier)
    return fixed_multiply

使用lambda语法可以更紧凑地编写:

def multiply_factory(multiplier):
    return lambda x: multiply_by(x, multiplier)

答案 4 :(得分:0)

如果你不能改变multiply_by()函数,最简单也许最好的方法可能是

def multiply_by_5(x):
    return multiply_by(x, 5)

如果你真的想要一个单行,你也可以使用lambda

但是,您可能希望将第一个功能更改为

def multiply_by(x, multiplier = 5):
    return x * multiplier

然后你可以做以下任何一种:

print(multiply_by(4, 3))
12

print(multiply_by(2))
10