我被困在我怀疑很简单的东西上,但我无法绕过它。我正在尝试使用可以在运行中重新定义的方法创建一个类。我希望能够为任意数量的实例执行此操作,但为了简单起见,我只在这里显示两个。
这是我的代码的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)
的值会发生变化?
答案 0 :(得分:0)
它会发生变化,因为您正在修改x
和y
全局变量,这些变量由您定义的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
在您交换x
和y
之后,您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
最终会修复x
和y
的值,就像定义函数时一样,这样当你随后交换它们并不影响该功能。