为什么对象 属性 中的存储函数被覆盖 (Python)?
Why is a stored function in an object property being overwritten (Python)?
以下是我的问题的最小工作示例,其中我有一个包含鱼对象数组的学校对象,我希望每条鱼都具有基于其索引的属性。我所做的只是设置属性,然后在初始化期间和稍后 class 完全实例化后将它们打印出来。问题是设置这些属性似乎对函数不起作用。此外,根据是否使用枚举(我想了解),它的表现也有所不同。
在下面的代码中,输出显示我学校对象中鱼的 'func' 属性 被覆盖,但 'x' 属性 没有.
class Fish:
def __init__(self):
self.x = -1
self.func = lambda y: -1
class School:
def __init__(self):
self.fishList = [Fish() for i in range(2)]
for fishIndex, f in enumerate(self.fishList):
f.x = fishIndex
f.func = lambda y: fishIndex
print("No enumerate:")
for f in self.fishList:
print(f.x, f.func(0))
print("Enumerate")
for fishIndex, f in enumerate(self.fishList):
print(f.x, f.func(0))
mySchool = School()
print("-----------------------------------------")
print("No enumerate:")
for f in mySchool.fishList:
print(f.x, f.func(0))
print("Enumerate:")
for fishIndex, f in enumerate(mySchool.fishList):
print(f.x, f.func(0))
输出:
No enumerate:
0 1
1 1
Enumerate
0 0
1 1
-----------------------------------------
No enumerate:
0 1
1 1
Enumerate:
0 1
1 1
到目前为止,我已经追踪到问题源于我如何储存鱼。如果我将鱼单独存储,而不是存储在数组中,则函数会正确保存。所以这让我认为这是一个 mutability/pointers 问题。但如果是这种情况,我预计 'x' 也不会正确坚持。
编辑:澄清一下,在输出中,虚线之前的第一个“枚举”是我对所有输出的预期。
在func
的定义中,fishIndex
是一个自由变量。这意味着名称本身,而不是 fishIndex
的当前值,是函数定义的一部分。
当函数被调用时,它会使用__init__
.
中定义的局部变量fishIndex
的当前值
在 __init__
中,当您将它用作 for
循环中的索引变量时,该变量会发生变化。
在__init__
之外,fishIndex
仍然引用__init__
中定义的变量,即使那个函数returns。我们说 func
是一个 闭包 在其定义范围内的变量上。
您在全局范围内的循环中重复使用名称 fishIndex
的事实不会影响 func
.
的行为
以下是我的问题的最小工作示例,其中我有一个包含鱼对象数组的学校对象,我希望每条鱼都具有基于其索引的属性。我所做的只是设置属性,然后在初始化期间和稍后 class 完全实例化后将它们打印出来。问题是设置这些属性似乎对函数不起作用。此外,根据是否使用枚举(我想了解),它的表现也有所不同。
在下面的代码中,输出显示我学校对象中鱼的 'func' 属性 被覆盖,但 'x' 属性 没有.
class Fish:
def __init__(self):
self.x = -1
self.func = lambda y: -1
class School:
def __init__(self):
self.fishList = [Fish() for i in range(2)]
for fishIndex, f in enumerate(self.fishList):
f.x = fishIndex
f.func = lambda y: fishIndex
print("No enumerate:")
for f in self.fishList:
print(f.x, f.func(0))
print("Enumerate")
for fishIndex, f in enumerate(self.fishList):
print(f.x, f.func(0))
mySchool = School()
print("-----------------------------------------")
print("No enumerate:")
for f in mySchool.fishList:
print(f.x, f.func(0))
print("Enumerate:")
for fishIndex, f in enumerate(mySchool.fishList):
print(f.x, f.func(0))
输出:
No enumerate:
0 1
1 1
Enumerate
0 0
1 1
-----------------------------------------
No enumerate:
0 1
1 1
Enumerate:
0 1
1 1
到目前为止,我已经追踪到问题源于我如何储存鱼。如果我将鱼单独存储,而不是存储在数组中,则函数会正确保存。所以这让我认为这是一个 mutability/pointers 问题。但如果是这种情况,我预计 'x' 也不会正确坚持。
编辑:澄清一下,在输出中,虚线之前的第一个“枚举”是我对所有输出的预期。
在func
的定义中,fishIndex
是一个自由变量。这意味着名称本身,而不是 fishIndex
的当前值,是函数定义的一部分。
当函数被调用时,它会使用__init__
.
fishIndex
的当前值
在 __init__
中,当您将它用作 for
循环中的索引变量时,该变量会发生变化。
在__init__
之外,fishIndex
仍然引用__init__
中定义的变量,即使那个函数returns。我们说 func
是一个 闭包 在其定义范围内的变量上。
您在全局范围内的循环中重复使用名称 fishIndex
的事实不会影响 func
.