[Python-Dev] PEP 351, the freeze protocol

Raymond Hettinger raymond.hettinger at verizon.net
Mon Oct 24 17:49:35 CEST 2005


[Barry Warsaw]
> I've had this PEP laying around for quite a few months.  It was
inspired
> by some code we'd written which wanted to be able to get immutable
> versions of arbitrary objects.


* FWIW, the _as_immutable() protocol was dropped from sets.py for a
reason.  User reports indicated that it was never helpful in practice.
It added complexity and confusion without producing offsetting benefits.

* AFAICT, there are no use cases for freezing arbitrary objects when the
object types are restricted to just lists and sets but not dicts,
arrays, or other containers.  Even if the range of supported types were
expanded, what applications could use this?  Most apps cannot support
generic substitution of lists and sets -- they have too few methods in
common -- they are almost never interchangeable.

* I'm concerned that generic freezing leads to poor design and
hard-to-find bugs.  One class of bugs results from conflating ordered
and unordered collections as lookup keys.  It is difficult to assess
program correctness when the ordered/unordered distinction has been
abstracted away.  A second class of errors can arise when the original
object mutates and gets out-of-sync with its frozen counterpart.

* For a rare app needing mutable lookup keys, a simple recipe would
suffice:

    freeze_pairs = [(list, tuple), (set, frozenset)]
    
    def freeze(obj):
        try:
            hash(obj)
        except TypeError:
            for sourcetype, desttype in freeze_pairs:
                if isinstance(obj, sourcetype):
                    return desttype(obj)
            raise
        else:
            return obj

Unlike the PEP, the recipe works with older pythons and is trivially
easy to extend to include other containers.

* The name "freeze" is problematic because it suggests an in-place
change.  Instead, the proposed mechanism creates a new object.  In
contrast, explicit conversions like tuple(l) or frozenset(s) are obvious
about their running time, space consumed, and new object identity.  

Overall, I'm -1 on the PEP.  Like a bad C macro, the proposed
abstraction hides too much.  We lose critical distinctions of ordered vs
unordered, mutable vs immutable, new objects vs in-place change, etc.
Without compelling use cases, the mechanism smells like a
hyper-generalization.


Raymond



More information about the Python-Dev mailing list