[Python-Dev] Dict constructor

Alex Martelli aleax@aleax.it
Sat, 13 Jul 2002 15:42:46 +0200


On Saturday 13 July 2002 03:04 pm, Guido van Rossum wrote:
	...
> > 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__.
>
> Reasonable.
	...
> This would run into similar problems as the PEP's auto-freeze approach
> when using "s1 in s2".  If s1 is a mutable set, this creates an
> immutable copy for the test and then throws it away.  The PEP's
> problem is that it's too easy to accidentally freeze a set; the
> problem with your proposal is "merely" one of performance.  Yet I
> think both are undesirable, although I still prefer your solution.

If performance is a problem (and I can well see it might be!) then
Set.__contains__(self, x) needs to use a specialized version of
the ad-hoc adaptation code I proposed for insertion:

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

One possible route to such optimization is to introduce another class, called 
_TemporarilyImmutableSet, able to wrap a MutableSet x, have the same hash 
value that x would have if x were immutable, and compare == to whatever x
compares == to.

Set would then expose a private method _asTemporarilyImmutable.
ImmutableSet._asTemporarilyImmutable would just return self;
MutableSet._asTemporarilyImmutable would return _TemporarlyImmutableSet(self).

Then:

    class Set(object):
        ...
        def __contains__(self, item):
            try: item = item._asTemporarilyImmutable()
            except AttributeError: pass
            return item in self.data


Alex