为什么在运行时重新定义的此方法不保留其值?

时间:2016-08-20 08:25:28

标签: python python-3.x global-variables

我被困在我怀疑很简单的东西上,但我无法绕过它。我正在尝试使用可以在运行中重新定义的方法创建一个类。我希望能够为任意数量的实例执行此操作,但为了简单起见,我只在这里显示两个。

这是我的代码的MWE:

class Foo():
    def __init__(self, z):
        self.z = z

    def f(self, t):
        return 0

def f(obj1, obj2, t):
    return (obj1.z - obj2.z) * t

a, b = Foo(3), Foo(5)
print(a.f(1), b.f(1)) # --> 0, 0

x, y = a, b
x.f = lambda t: f(x, y, t)
print(a.f(1), b.f(1)) # --> -2, 0

x, y = b, a
x.f = lambda t: f(x, y, t)
print(a.f(1), b.f(1)) # --> 2, 2

为什么a.f(1)的值会发生变化?

1 个答案:

答案 0 :(得分:0)

它会发生变化,因为您正在修改xy全局变量,这些变量由您定义的f函数引用:

In [2]: a, b = Foo(3), Foo(5)

In [3]: print(a.f(1), b.f(1))
0 0

In [4]: x, y = a, b
   ...: x.f = lambda t: f(x, y, t)
   ...: print(a.f(1), b.f(1))
   ...: 
-2 0

In [5]: x, y = b, a 

In [6]: print(a.f(1), b.f(1))  # you changed x and y
2 0

在您交换xy之后,您a.f就是lambda t: f(x, y, t)这个函数,这意味着它会调用f(b, a, t),因为b = Foo(5)a = Foo(3) 5-3 == 2代替-2

如果您想修复f和"取消链接"所传递的值它来自全局变量,您可以使用默认参数:

In [2]: x, y = a, b
   ...: x.f = lambda t, x=x, y=y: f(x, y, t)
   ...: 

In [3]: print(a.f(1), b.f(1))
-2 0

In [4]: x, y = b, a

In [5]: print(a.f(1), b.f(1))
-2 0

由于默认值是在定义时评估的,因此使用lambda t, x=x, y=y最终会修复xy的值,就像定义函数时一样,这样当你随后交换它们并不影响该功能。