1

I can't understand how x and y are the same list. I've been trying to debug it using print statements and import code; code.interact(local=locals()) to drop into various points, but I can't figure out what on earth is going on :-(

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]
Casebash
  • 114,675
  • 90
  • 247
  • 350

2 Answers2

7

The problem is with this line:

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

The lambda uses the value of the variable key, but that value has changed by the time the lambda is called - so all lambdas will actually use the same value for the key.

This can be fixed with a little trick: Pass the key as a default parameter value to the lambda:

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

This makes sure that the value of key is bound to the one it had at the time the lambda was created.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • Wow, lambdas can have default values? I never knew that! – Casebash Feb 16 '10 at 10:47
  • -1: Replacing the lambda entirely is far, far better than fixing it. In this class, it's not clear *why* the key-value lookup must be a lambda in the first place. Indeed, it's not clear why this isn't just a subclass of `OrderedDict`. – S.Lott Feb 16 '10 at 10:55
0

I think the following line should look like this (but unfortunately I can't test because I don't have Python 3 available):

# Then functions to access them
d = dict((key, lambda self: self.__vals__[key]) for key in objects_type)
tux21b
  • 90,183
  • 16
  • 117
  • 101