Can someone please explain the best way for me to map from one instance to another? In the following code either: (1) I am using dictionaries wrong, or (2) I'm missing something with ExtensionClass in general. I have tried searching Zope and Python mailing lists and resources for an answer to this question but have become confused by different conflicting messages. On the one hand I have heard that dictionary keys are supposed to be immutable. On the other, I've heard that dictionaries are used to simulate (key is object, value is ignored) some aspects of sets. Which is correct? What I really want is to be able to map a Persistent object to a string with fast lookup. Thanks for any help. John Heintz import ZODB from Persistence import Persistent class Test1: pass class Test2(Persistent): pass dict = {} t1 = Test1() t2 = Test2() try: dict[t1] = 1 except: print "Using instance of Test1 as key failed!" try: dict[t2] = 2 except: print "Using instance of Test2(Persistent) as key failed!" -- John D. Heintz DataChannel, Inc. Senior Engineer 512-633-1198 jheintz@isogen.com
On Tue, Sep 19, 2000 at 09:41:57AM -0500, John D. Heintz wrote:
Can someone please explain the best way for me to map from one instance to another?
In the following code either: (1) I am using dictionaries wrong, or (2) I'm missing something with ExtensionClass in general.
I have tried searching Zope and Python mailing lists and resources for an answer to this question but have become confused by different conflicting messages. On the one hand I have heard that dictionary keys are supposed to be immutable. On the other, I've heard that dictionaries are used to simulate (key is object, value is ignored) some aspects of sets. Which is correct?
What I really want is to be able to map a Persistent object to a string with fast lookup.
Thanks for any help. John Heintz
import ZODB from Persistence import Persistent
class Test1: pass
class Test2(Persistent): pass
dict = {} t1 = Test1() t2 = Test2()
try: dict[t1] = 1 except: print "Using instance of Test1 as key failed!"
try: dict[t2] = 2 except: print "Using instance of Test2(Persistent) as key failed!"
From the Python Library Reference:
"""A dictionary's keys are almost arbitrary values. The only types of values not acceptable as keys are values containing lists or dictionaries or other mutable types that are compared by value rather than by object identity.""" And from the Python Reference Manual: """__hash__ (self) Called for the key object for dictionary operations, and by the built-in function hash(). Should return a 32-bit integer usable as a hash value for dictionary operations. The only required property is that objects which compare equal have the same hash value; it is advised to somehow mix together (e.g., using exclusive or) the hash values for the components of the object that also play a part in comparison of objects. If a class does not define a __cmp__() method it should not define a __hash__() operation either; if it defines __cmp__() but not __hash__() its instances will not be usable as dictionary keys. If a class defines mutable objects and implements a __cmp__() method it should not implement __hash__(), since the dictionary implementation requires that a key's hash value is immutable (if the object's hash value changes, it will be in the wrong hash bucket).""" So, if you want to be able to use a Persistent based object as keys to a dictionary, implement __cmp__ and __hash__ methods on that class:
import ZODB from Persistence import Persistent class Test1: ... pass ... class Test2(Persistent): ... def __cmp__(self): return 1 ... def __hash__(self): return 1 ... dict = {} t1 = Test1() t2 = Test2() dict[t1] = 1 dict[t2] = 2 dict {<Test2 instance at 80b3aa0>: 2, <__main__.Test1 instance at 80a3e78>: 1}
-- Martijn Pieters | Software Engineer mailto:mj@digicool.com | Digital Creations http://www.digicool.com/ | Creators of Zope http://www.zope.org/ ---------------------------------------------
Thanks for the reply Martijn, I do want the objects of Test2 class to be compared by identity, like I'm assuming Test1 objects are. If I have to define __cmp__ and __hash__ then I will basically be making them up because the object in question are mutable - except for their identity. Why do the Python class instances naturally act as dictionary keys while the ExtensionClass instances don't? Thanks for the time, John Martijn Pieters wrote:
From the Python Library Reference:
"""A dictionary's keys are almost arbitrary values. The only types of values not acceptable as keys are values containing lists or dictionaries or other mutable types that are compared by value rather than by object identity.""" <...>
So, if you want to be able to use a Persistent based object as keys to a dictionary, implement __cmp__ and __hash__ methods on that class:
import ZODB from Persistence import Persistent class Test1: ... pass ... class Test2(Persistent): ... def __cmp__(self): return 1 ... def __hash__(self): return 1 ... dict = {} t1 = Test1() t2 = Test2() dict[t1] = 1 dict[t2] = 2 dict {<Test2 instance at 80b3aa0>: 2, <__main__.Test1 instance at 80a3e78>: 1}
-- Martijn Pieters | Software Engineer mailto:mj@digicool.com | Digital Creations http://www.digicool.com/ | Creators of Zope http://www.zope.org/ ---------------------------------------------
-- John D. Heintz DataChannel, Inc. Senior Engineer 512-633-1198 jheintz@isogen.com
Thanks for the reply Martijn, I do want the objects of Test2 class to be compared by identity, like I'm assuming Test1 objects are. If I have to define __cmp__ and __hash__ then I will basically be making them up because the object in question are mutable - except for their identity. Why do the Python class instances naturally act as dictionary keys while the ExtensionClass instances don't? Thanks for the time, John Martijn Pieters wrote:
From the Python Library Reference:
"""A dictionary's keys are almost arbitrary values. The only types of values not acceptable as keys are values containing lists or dictionaries or other mutable types that are compared by value rather than by object identity.""" <...>
So, if you want to be able to use a Persistent based object as keys to a dictionary, implement __cmp__ and __hash__ methods on that class:
import ZODB from Persistence import Persistent class Test1: ... pass ... class Test2(Persistent): ... def __cmp__(self): return 1 ... def __hash__(self): return 1 ... dict = {} t1 = Test1() t2 = Test2() dict[t1] = 1 dict[t2] = 2 dict {<Test2 instance at 80b3aa0>: 2, <__main__.Test1 instance at 80a3e78>: 1}
-- Martijn Pieters | Software Engineer mailto:mj@digicool.com | Digital Creations http://www.digicool.com/ | Creators of Zope http://www.zope.org/ ---------------------------------------------
-- John D. Heintz DataChannel, Inc. Senior Engineer 512-633-1198 jheintz@isogen.com
On Thu, Sep 21, 2000 at 08:00:29AM -0500, John D. Heintz wrote:
Thanks for the reply Martijn,
I do want the objects of Test2 class to be compared by identity, like I'm assuming Test1 objects are.
If I have to define __cmp__ and __hash__ then I will basically be making them up because the object in question are mutable - except for their identity.
I don't think that in this case __cmp__ has to be implemented; you just use the default behaviour of object identity comparison. All you need to do is then implent a __hash__() method that will return a 32-bit integer that is unique to the object. You could base this on repr(self).
Why do the Python class instances naturally act as dictionary keys while the ExtensionClass instances don't?
ExtensionClasses pretend to be Python classes, but are not succeeding everywhere. I am not that deeply knowledgable about Extension Classes, so I cannot tell you why exactly you see this difference.
Martijn Pieters wrote:
From the Python Library Reference:
"""A dictionary's keys are almost arbitrary values. The only types of values not acceptable as keys are values containing lists or dictionaries or other mutable types that are compared by value rather than by object identity."""
<...>
So, if you want to be able to use a Persistent based object as keys to a dictionary, implement __cmp__ and __hash__ methods on that class:
import ZODB from Persistence import Persistent class Test1: ... pass ... class Test2(Persistent): ... def __cmp__(self): return 1 ... def __hash__(self): return 1 ... dict = {} t1 = Test1() t2 = Test2() dict[t1] = 1 dict[t2] = 2 dict {<Test2 instance at 80b3aa0>: 2, <__main__.Test1 instance at 80a3e78>: 1}
-- John D. Heintz DataChannel, Inc. Senior Engineer 512-633-1198 jheintz@isogen.com
-- Martijn Pieters | Software Engineer mailto:mj@digicool.com | Digital Creations http://www.digicool.com/ | Creators of Zope http://www.zope.org/ ---------------------------------------------
participants (2)
-
John D. Heintz -
Martijn Pieters