Monday, April 11, 2005

For the first time in my life, I find myself worried about mutability.

I want to take advantage of Python's new sets (who wouldn't?). It turns out that sets can only be made of immutable, hashable objects, and a user-created object type is (by definition) mutable.

I can see where it makes sense. If I say
box1 = Box(contents='eggs')
box2 = Box(contents='eggs')
basket = set([box1, box2])
should basket contain one or two items?
Now suppose I
box2.contents = 'yogurt'
Now does my basket have a box of eggs and a box of yogurt, or just one box of yogurt? It's not clear.

The problem is, there are objects I will create that truly never will change, and it truly would be useful to use this wonderful set functionality with them. So now I'd like to be able to create immutable objects, but Python has no particular way to create them.

The only way I've found so far feels a little bit dangerous - to define __hash__. As far as I can tell, it means "You can know me by this". If I do forget and later change data that is the basis of my hash, my object no longer hashes to what it once did - it has moved and left no forwarding address. There are some clumsy ways to try to block later changes to my object's values, but they are... clumsy. (Redefining the object's __setattr__ and raising exceptions therein. Ick.)

Thus, it feels like I'm delving into eldritch secrets, like my soul is toast if I scuff the pentagram. __str__ and __cmp__ are the only double-underscore methods I'd defined previously. They feel downright warm and fuzzy compared to this.

No comments: