storing meta data on dictionary keys
Erik Jones
erik at myemma.com
Wed Oct 10 00:18:37 EDT 2007
On Oct 9, 2007, at 7:37 PM, Andreas Kraemer wrote:
> From: Chris Mellon <arkanes at gmail.com>
> Sent: Tuesday, October 9, 2007 1:51:04 PM
>
> > Because, by definition, if you have the key then you don't need
> to get
> > it from the dict. What you're doing here is conflating 2 mappings
> into
> > one: string value->person and person->values. Use 2 explicit
> dicts to
> > make it clear what you're going, or use one dict and store a
> tuple of
> > values: person, friends = d["John"].
>
> No, that was not the point.
>
> I don't want the meta data to be used in the dictionary look-up,
> and in fact I want to be able to modify or delete it later w/o
> affecting dictionary look-up. In the toy example "John" and Str
> ("John") are two different objects that map to the same value in
> the dictionary, and "John" == Str("John") is True, since class Str
> (str) inherits __hash__() and __eq__() from str. IOW, if John dyes
> his hair, his friends shouldn't change :-)
>
> Apart from this silly example I really encountered this issue when
> using the networkx library. As I mentioned, graph nodes are stored
> as dictionary keys there, i.e. nodes can be arbitrary objects with
> the only requirement to be hashable, and I am stuck with this data
> structure when using the library. In my example nodes are uniquely
> identified by their name (a string) but may carry other attributes,
> like their display color and shape, that are not used to identify a
> node. Therefore, I thought, subclassing str would be the simplest,
> most straightforward structure for a node object.
>
> Of course there are workarounds (e.g. get all keys with keys()),
> but I thought something similar to a get_key() dictionary method
> would be the easiest way to retrieve the actually stored key
> object, and I was just surprised to discover that no such method
> does exist ....
So, do you not keep references to your nodes anywhere but the actual
graph dict? I kind of agree with Chris here in that two dicts will
work. One for the nodes, indexed by their strings. And, to use the
actual nodes as keys simply override __hash__ in your Node object
classes.
>>> class Node(object):
... def __init__(self, name, **kwargs):
... self.name = name
... for k, v in kwargs.items():
... self.__dict__[k] = v
...
... def __hash__(self):
... return hash(self.name)
...
>>> nodes = {}
>>> graph = {}
>>>
>>> n = Node('foo')
>>> m = Node('blah', baz=5)
>>>
>>> nodes[n.name] = n
>>> nodes[m.name] = m
>>>
>>> for name, node in nodes.items():
... graph[node] = "whatever for node %s" % name
...
>>> nodes{'blah': <__main__.Node object at 0x76c50>, 'foo':
<__main__.Node object at 0x76d30>}
>>> graph{<__main__.Node object at 0x76c50>: 'whatever for node
blah', <__main__.Node object at 0x76d30>: 'whatever for node foo'}
>>> graph[nodes['foo']]'whatever for node foo'
Erik Jones
Software Developer | Emma®
erik at myemma.com
800.595.4401 or 615.292.5888
615.292.0777 (fax)
Emma helps organizations everywhere communicate & market in style.
Visit us online at http://www.myemma.com
More information about the Python-list
mailing list