[Python-Dev] Dict constructor

Alex Martelli aleax@aleax.it
Sat, 13 Jul 2002 10:51:59 +0200


On Saturday 13 July 2002 09:12 am, Tim Peters wrote:
> [Guido]
>
> > ...
> > Let's do a set module instead.  There's only one hurdle to take
> > for a set module, and that's the issue with using mutable sets as
> > keys.  Let's just pick one solution and implement it (my favorite
> > being that sets simply cannot be used as keys, since it's the
> > simplest, and matches dicts and lists).
>
> I want a set module, but if I finish Greg's abandoned work I want sets of
> sets too.  Sets don't have "keys", they're conceptually collections of
> values, and it would be as odd not to allow sets containing sets as not to
> allow lists containing lists, or to ban dicts as dict values.  Greg needed
> sets of sets for his work, and I've often faked them too.  I'm not going to

I agree that having sets without having sets of sets would not be anywhere
as useful.

> be paralyzed by that combining mutable sets with sets of sets requires that
> some uses of set-as-set-element will be expensive, fragile, and/or hard to
> explain.  If you don't want that pain, don't play that game.  If you do

What about the following compromise: there are two set types, ImmutableSet 
and MutableSet, with a common supertype Set.  ImmutableSet adds __hash__,
while MutableSet adds insert and remove, to the common core of methods
inherited from Set, such as __contains__ and __iter__.  It's easy to make a
MutableSet instance m from an ImmutableSet instance x, such that m == x,
either by letting each __init__ accept an argument of the other kind (maybe
just a special case of such an __init__ accepting any iterable), or, if that 
can afford very substantial performance improvements, via ad-hoc methods.

The second part of the puzzle is that hash(x) tries to adapt x to the Hashable
protocol before calling x.__hash__.  Types that are already hashable adapt
to Hashable by just returning the same instance, of course.  A MutableSet
instance adapts to Hashable by returning the equivalent ImmutableSet.

Since it's apparently too wild an idea to say "adapt to protocol" when one
means "adapt to protocol", at least for the next few releases (and that, in
the optimistic hypothesis that my future rewrite of the adaptation PEP is
favorably received), there will of course need to arise yet another special
purpose way to express this same general idea, such as:


class MutableSet(Set):
    ...
    def insert(self, item):
        try: item = item.asSetItem()
        except AttributeError: pass
        self.data[item] = True

    def asSetItem(self):
        return ImmutableSet(self)


or the like.  


Alex