2010-02-16 3 views
1

Je ne peux pas comprendre comment x et y sont la même liste. J'ai essayé de le déboguer en utilisant des instructions d'impression et import code; code.interact(local=locals()) de tomber dans divers points, mais je ne peux pas comprendre ce que sur la terre qui se passe :-(Pourquoi ces listes sont-elles les mêmes?

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] 
+0

Je pense que c'est le même problème qu'ici: http://stackoverflow.com/questions/1867068/python-reference-problem – Ikke

+0

Pourquoi n'est-ce pas juste une sous-classe de 'OrderedDict'? –

+0

C'est le même problème avec la liaison de noms comme ici: http://stackoverflow.com/questions/139819/why-results-of-map-and-list-comprehension-are-different – jfs

Répondre

7

le problème est avec cette ligne:

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

le lambda utilise la valeur de la variable key, mais cette valeur a changé au moment où le lambda est appelé - donc tous les lambda utiliseront la même valeur pour la clé.

Cela peut être corrigé avec une petite astuce: passer la clé comme une valeur de paramètre par défaut lambda:

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

Ceci assure que la valeur de key est lié à celui qu'il avait à l'époque le lambda a été créé.

+0

Wow, lambdas peut avoir des valeurs par défaut? Je n'ai jamais su cela! – Casebash

+0

-1: Remplacer entièrement le lambda est loin, bien mieux que de le réparer. Dans cette classe, il n'est pas clair * pourquoi * la recherche de valeur-clé doit être un lambda en premier lieu. En effet, il n'est pas clair pourquoi ce n'est pas juste une sous-classe de 'OrderedDict'. –

0

Je pense que devrait ressembler à la ligne suivante comme ce (mais je ne peux malheureusement pas tester parce que je n'ai pas Python 3 disponibles):

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

Python a ajouté des compréhensions de dictionnaire, donc je n'ai pas besoin d'utiliser la fonction dict – Casebash

Questions connexes