对象列表功能不起作用

时间:2016-02-17 17:13:00

标签: python function

对不起标题,我希望它能正确反映我的问题:

在下面的代码中,我期望结果为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())

4 个答案:

答案 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”,因此您从最后一个对象获得相同的数字。