Thoughts about Python

Mike C. Fletcher mcfletch at rogers.com
Tue Feb 24 22:30:50 CET 2004


Marco Aschwanden wrote:
...

>Maybe I don't get the point here: Why do dictionaries need tuples to
>work? I know that tuples can be used as keys... but how many times do
>you need tuples as dictionary keys (it would be simple to turn a list
>into an immutable string if really needed ("::".join(["a","b"]). But
>maybe tuples are used within dictionary in a way I don't know. If you
>could clarify on this point I will never ever say anything about
>"useless" tuples... instead I will start asking for "immutable
>dictionaries" 8o)
>  
>
    x = [1,2]
    d = { x : 32 }
    x.append( 3 )
    d[ [1,2] ]

Does that last line raise a key-error, or return 32?  Tuples are useful 
as keys precisely because they are immutable, and hash based on their 
contents/value.  Mutable keys in dictionaries either need to be 
"identity" based (which is far less useful that "value" based, (as then 
you can only test whether a particular list is used as a key, not any 
list with the same value)), or have some funky book-keeping rules 
regarding what happens when the key changes (for example, convert the 
key to a tuple under the covers so that all further changes to the key 
are ignored in the dictionary).

To clarify regarding identity:

    x = (1,2)
    d = { x : 32 }
    d[ x ]
    d[ (1,2) ]

because they hash and compare based on value, tuples here can 
unambiguously be used as value-based keys.  With a list, were we to use 
identity-based comparisons:

    x = [1,2]
    d = { x : 32 }
    d[ x ] # would return a value
    d[ [1,2] ] # would raise a key-error,
    # defeating one of the most common usage patterns for
    tuples-in-dictionaries

while if we were to use value-based comparisons set at key-specification 
time:

    x = [1,2]
    d = { x: 32 }
    x.append( 3 ) # possibly done in another thread...
    del d[ x ] # would raise a key-error

to do lots of common operations (such as iterating through the keys of a 
dictionary and deleting those which meet a particular test) in this 
scenario you'd need to be able to return a static key in order to be 
sure not to have it mutate while you're working, so you'd need an 
exposed list-like immutable data-type (sound familiar).

Now, as shown above, we could do an explicit cast on setting a 
dictionary value to make a list a tuple "under the covers" and thus get 
back... but this is another "explicit is better than implicit" things.  
The magic would up and bite in debugging weird corner cases more times 
than it saved you a few seconds of thinking in the design stage.  We 
still have the static type, it would need to be dealt with in code, and 
it would be surprising to see it show up instead of the lists we 
originally used as the keys.

Using lists forced to strings would be a difficult sell even without the 
problems described above, particularly as you can quite readily have 
strings as keys already, so you get difficult-to-debug collisions where 
a string just happens to equal the string-ified list representation of 
some other value.  The "explicit is better than implicit" axiom of 
"import this" would then suggest that having an explicitly defined 
immutable type (tuple) that hashes by value and is used to set keys in a 
dictionary is a better choice than automagically coercing the lists to a 
hidden type (or a string).

Don't worry about asking questions like this, by the way, it's good for 
the perceptions of the community to be stirred every once in a while.  
Enjoy yourself,
Mike

_______________________________________
  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://members.rogers.com/mcfletch/





More information about the Python-list mailing list