关于python:为什么这些列表相同?

Why are these lists the same?

我不明白x和y是如何构成同一个列表的。我一直试图用print语句和import code; code.interact(local=locals())来调试它,但我不知道到底发生了什么:-(

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from collections import namedtuple, OrderedDict

coordinates_2d=["x","y"]

def virtual_container(virtual_container, objects_type):
   """Used to create a virtual object given a the type of container and what it holds.
    The object_type needs to only have normal values."""

    if issubclass(virtual_container, list):
        class my_virtual_container_class:
           """This singleton class represents the container"""
            def __init__(self):
                #Define the default values
                __vals__=OrderedDict([(key,list()) for key in objects_type])
                print(id(__vals__["x"]), id(__vals__["y"]))#ids are different: 12911896 12911968
                #Then functions to access them
                d={key: lambda self: self.__vals__[key] for key in objects_type}
                d["__vals__"]=__vals__
                #Construct a named tuple from this
                self.attr=type('attr_cl',(), d)()
                print(id(self.attr.x()), id(self.attr.y()))#ids are same: 32904544 32904544
            #TODO: Define the operators __del__, setitem, getitem. Also append
        return my_virtual_container_class()

#Nice method of handling coordinates
coordinates=virtual_container(list, coordinates_2d)
x=coordinates.attr.x()
y=coordinates.attr.y()
x.append(1)
y.append(2)
print(x, y)#Prints [1, 2] [1, 2]


这一行有问题:

1
d={key: lambda self: self.__vals__[key] for key in objects_type}

lambda使用变量EDOCX1的值(0),但该值在调用lambda时已发生更改,因此所有lambda实际上都将对键使用相同的值。

这可以通过一个小技巧来解决:将键作为默认参数值传递给lambda:

1
... lambda self, key=key: self.__vals__[key] ...

这样可以确保EDOCX1的值(0)与创建lambda时的值绑定在一起。


我认为下面这行应该是这样的(但不幸的是,我不能测试,因为我没有可用的python 3):

1
2
# Then functions to access them
d = dict((key, lambda self: self.__vals__[key]) for key in objects_type)