如何深度复制一个函数对象

4
我创建了一个函数,该函数返回由变量指定的值。例如:
y = 1.
def f(x):
    return y

我需要将此函数作为函数对象来创建另一个对象。
dist = dist.distribution(f, other_variables)

这个没问题。但如果我想创建几个不同的分布对象(具有不同函数 f 的意义在于 y 变化),该怎么办?比如:
dist = dist.distribution(f, other_variables)
y = 2.
dist2 = dist.distribution(f, other_variables)

然后所有的分布式对象都只返回最后一个指定的值 y。也就是说,
dist.f()(1.)
>>>> 2.
dist2.f()(1.)
>>>> 2.

与预期不同

dist.f()(1.)
>>>> 12.
dist2.f()(1.)
>>>> 2.

问题显然是函数f仅在调用时访问变量,而不是一次性访问。有什么解决办法吗?我最终想要的是:一个只有一个变量(x,在这种情况下它没有做任何事情,但在其他情况下需要),返回创建分布时y的值。因此,原则上我希望在初始化分布时对给定的函数进行深拷贝,这意味着它不再受任何变量更改的影响。这是否可能?
1个回答

6

不要使用全局变量。也不需要对函数进行“deepcopy”操作;y全局变量根本不是函数状态的一部分。

可以使用提供作用域值的函数工厂,或者使用functools.partial()为函数提供默认参数。

函数工厂:

def produce_f(y):
    def f(x):
        return y
    return f

dist = dist.distribution(produce_f(1.), other_variables)

现在,yf 的一个局部变量,每次调用 produce_f() 都会返回一个新的 f,并且 y 作为 f 的单元变量被存储。
演示:
>>> f1 = produce_f(12.)
>>> f2 = produce_f(42.)
>>> f1('foo')
12.0
>>> f2('foo')
42.0

使用 functools.partial()
from functools import partial

def f(y, x):
    return y

dist = dist.distribution(partial(f, 1.), other_variables)

这里,partial(f, 1.) 会生成一个新的可调用对象,每次调用时都会调用 f(1., ...),并将传入的任何额外参数附加到后面。

演示:

>>> f1 = partial(f, 12.)
>>> f2 = partial(f, 42.)
>>> f1('foo')
12.0
>>> f2('foo')
42.0

很酷,部分解决方案正是我寻找的答案... 我尝试了$produce_f(y)$的方法,但它没有奏效。也许我在设置y和生成f的时间上犯了错误。 这个按回车键发布的方式让我感到困惑,对于我的编辑我很抱歉^^ - user2267896
不,用这些技术是不行的。 - Martijn Pieters
谢谢您的及时回答,我明天会尝试。 - user2267896

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接