对不起标题,我希望它能正确反映我的问题:
在下面的代码中,我期望结果为0 1 2但是我有2 2 2. my_function 中的代码似乎是用的最后一个实例解释的OBJ 。有什么问题?
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
a_list = []
for index in range(3):
obj = Example(index)
def my_function(x):
#some stuff with x like obj.another_function(x)
return obj.get()
a_list.append(my_function)
for c in a_list:
print(c())
答案 0 :(得分:4)
定义此
时def my_function():
return obj.get()
Python将理解my_function
应该运行名为get()
的对象的obj
方法并返回该值。在您尝试调用它之前,它不会知道obj
的值以及get()
方法的作用。
所以,你实际上定义了三个不同的函数,最终将完成相同的事情。并且,最后,运行相同的代码三次。
但为什么返回2 2 2?
因为在最后一次迭代之后,obj
的值为Example(2)
*,因为您在每次迭代时重新定义其值,并且最后一次迭代仍然存在。
*
因为此行obj = Example(index)
答案 1 :(得分:3)
了解有关python如何工作的一些内容将有助于您了解此处发生的事情。这里obj
是一个闭包,闭包是在调用时计算的,而不是在定义函数时所以如果我这样做:
x = "hello"
def printX():
print x
x = "goodbye"
printX() # goodbye
我得到了#34;再见"因为printX
在我的模块中引用了一个全局变量,在我创建printX
后会发生变化。
您要做的是创建一个带有引用特定对象的闭包的函数。执行此操作的功能方法是创建一个返回另一个函数的函数:
x = "hello"
def makePrintX(a):
def printX():
# We print a, the object passed to `makePrintX`
print a
return printX
# x is evaluated here when it is still "hello"
myPrintX = makePrintX(x)
x = "goodbye"
myPrintX() # "hello"
如果您在理解上述示例时遇到问题,我建议您阅读python的范围规则。对于您的示例,您可以执行以下操作:
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
def makeObjFunction(obj):
def objFunction(x):
return obj.get()
return objFunction
a_list = []
for index in range(3):
obj = Example(index)
my_function = makeObjFunction(obj)
a_list.append(my_function)
for c in a_list:
print(c("some value"))
答案 2 :(得分:2)
您将三个my_functions附加到a_list,它们是同一个Example对象上的所有闭包。尝试:
def my_function():
return obj
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
您可以看到它们具有相同的ID,因此在每个上调用get()应该给出相同的答案。
如果您只是附加obj.get函数(并删除my_function),它将正常工作。
a_list.append(obj.get)
....
0
1
2
编辑:您已更新了问题,以便在my_function()中执行更多操作。它仍然基本上是一个范围问题。
def my_func_factory(p_obj):
def my_function(x):
#some stuff with x like obj.another_function(x)
return p_obj.get()
return my_function
for index in range(3):
obj = Example(index)
a_list.append(my_func_factory(obj))
由于my_function无法看到obj被重新分配,因此每个实例都不会接收更改。
答案 3 :(得分:0)
我认为append()
for
只是在a_list[]
附加功能地址。在for
次迭代后,a_list
确实被赋予了数字。然后它会发现my_function
的地址,然后他们得到my_function
中的数字,这就是2.这就是你得到[2,2,2]的原因。
或许,在my_function
中,函数给出“obj”的方法。但for
迭代每次都会更改“obj”内存地址,因此符号“obj”始终以最新对象Example
为目标。由于my_function
始终获得“obj”,因此您从最后一个对象获得相同的数字。