storing meta data on dictionary keys

Erik Jones erik at myemma.com
Thu Oct 11 00:00:58 EDT 2007


On Oct 10, 2007, at 6:40 PM, Andreas Kraemer wrote:

> On Oct 9, 9:18 pm, Erik Jones <e... at myemma.com> wrote:
>> 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.
>
> Yes, I guess that's exactly what I want. To keep things as simple as
> possible and not having to keep track of another dictionary. If you
> look at class Dict(dict) in the OP, simulating the behavior I'd liked
> to have seen for built-in dict itself, the second dictionary is
> actually hidden so I don't have to bother with it any more ...

If you're sure that 1.  this use case won't grow and 2. that you'll  
only be the only person ever using code, then it's your choice of  
preference.  Both of those points are equally important.  1 is a  
manageability issue in that you are complicating what could be an  
easy solution for a small gain in convenience -- one that could just  
as easily be had by encapsulating the management of both dicts in an  
explicit class or function/method.  Let me quote lines 2 through 5 of  
The Zen of Python (PEP20):

Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.

Using two dicts would be explicit, simple and flat.  Your's is none  
of those.

For point 2, if anyone else needs to work with your code they're most  
likely going to be confused as the implementation is overly complex.   
I know when I initially read through it I had to read it a couple  
times to assure myself of what it was doing because I was thinking  
that it seems that there's more going on than there is, so there must  
be.  Remember, the best solutions are those that not only you can  
understand, but the next guy/girl/?.

>
>> And, to use the
>> actual nodes as keys simply override __hash__ in your Node object
>> classes.
>
> The trivial "class Str(str): pass" in the OP (that already inherits
> the correct __hash__ and
> __eq__) serves the same purpose as your Node(object) below, except
> that self.name is stored
> in the str built-in, and there is no flashy initializer.

True, but you're breaking the intended abstraction of inheriting from  
str, i.e. the reason you can inherit from str is so that you can  
specialize strings, not get __has__ and __eq__ for free.  You can  
define those on your own for a reason.

>
>>
>>>>> 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'
>
> I still believe that it would be a nice-to-have, and probably only a
> small effort to equip
> the built-in dict with a get_key() method. The whole mechanism of
> dictionary look-up in Python,
> based on "duck typing", and only caring about the __hash__ and __eq__
> methods supplied by
> the key object, is constructed in a way that allows objects inserted
> into the dictionary as keys
> and objects used for look-up to be (non-trivially) distinct.
> Therefore, it would actually be
> nice to be able to retrieve keys from the dict in a direct way (other
> than via .keys()).
> The same may apply to sets and frozensets as well ...;-)

So, (explicitly:) you want the built-in dict to be a dictionary that  
also maintains a dictionary of its own keys?  Not likely to happen.   
Again, you're asking to have one dictionary act as two and that's  
just confusing.  I'm not saying that get_key is a bad idea for  
(possibly) some use cases, just that what you're actually doing is  
creating a dictionary wherein the same key can return two different  
object depending on the retrieval method used and that is NOT what  
the built-in dict is for.  In fact, now that I think of it, get_key  
is probably a bad name for it, get_other_object_with_this_same_key is  
probably more apt :)

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