Easy immutability in python?

Discussion in 'Python' started by Terry Hancock, Mar 4, 2006.

  1. Is there an *easy* way to make an object immutable in
    python? Or perhaps I should say "one obvious way to do it"?
    Oughtn't there to be one?

    I've found a thread on how to do this[1], which essentially
    says something like "redefine __setattr__, __delattr__,
    __hash__, __eq__, __setitem__, delitem__ ... and probably
    some other stuff too".

    [1]

    Yet, what you have to do is pretty mechanical (e.g. all the
    mutators have to raise NotImplementedError and the hashes
    and comparisons seem like they have obvious defaults).

    Given that I have some kind of container, like an overloaded
    list, and I just say "oh, I need that to be immutable, like
    a tuple" -- it would be nice to just be able to declare it
    so. I just want this for QA purposes -- I have a pretty
    complex system, and I want the programmer to be warned when
    he accidentally tries to change an immutable enumeration or
    redefine a symbol.

    I know a (hard and error-prone) way to do it, but I'm
    thinking there must be a "smart" way to do it.

    Is there some way to do that with, e.g. decorators?

    (I haven't really figured out why I should want decorators,
    is this a use case?).

    Or maybe I should make an "Immutable" class, and just
    inherit from it last so it overloads everything else with
    the null interfaces?

    --
    Terry Hancock ()
    Anansi Spaceworks http://www.AnansiSpaceworks.com
    Terry Hancock, Mar 4, 2006
    #1
    1. Advertising

  2. Terry Hancock

    Guest

    Since this is a container that needs to be "immutable, like a tuple",
    why not just inherit from tuple? You'll need to override the __new__
    method, rather than the __init__, since tuples are immutable:

    class a(tuple):
    def __new__(cls, t):
    return tuple.__new__(cls, t)

    cheers,
    Jess
    , Mar 4, 2006
    #2
    1. Advertising

  3. Terry Hancock

    Guest

    To be clear, in this simple example I gave you don't have to override
    anything. However, if you want to process the values you place in the
    container in some way before turning on immutability (which I assume
    you must want to do because otherwise why not just use a tuple to begin
    with?), then that processing should take place in a.__new__.

    cheers,
    Jess
    , Mar 4, 2006
    #3
  4. On 4 Mar 2006 10:14:56 -0800
    wrote:
    > Since this is a container that needs to be "immutable,
    > like a tuple", why not just inherit from tuple? You'll
    > need to override the __new__ method, rather than the
    > __init__, since tuples are immutable:
    >
    > class a(tuple):
    > def __new__(cls, t):
    > return tuple.__new__(cls, t)


    The reason this is undesireable, is because in the typical
    use-case, I want to have TWO kinds of objects, one mutable,
    and one immutable. Just like tuple / list. I would prefer
    not to have to implement them completely separately. So
    far, it's usually simpler to implement the mutable type
    first -- the need for immutability semantics usually arises
    after you have a mutable version.

    But undoing mutability apparently is like making a sieve
    watertight -- it would've been easier to design a ladle and
    then put holes in it, than to design a sieve and then stop
    up the holes.

    In fact, my particular case wants to subclass Set and
    ImmutableSet -- their contents, though, are also immutables
    in principle. In fact the elements are similar to "int" or
    "str", but I don't want to subclass those, because I don't
    want them to have math methods or string methods.

    I've considered several different approaches to this. One is
    to create a "BaseVocabulary" as an abstract class, from
    which the mutable and immutable types are drawn, and then
    mix it in with Set and ImmutableSet:

    class BaseVocabulary(object):
    def __init__(self, values):
    self._data = values
    # (or something like that)
    # other functionality

    class Vocabulary(Set, BaseVocabulary):
    # stuff appropriate for the "open" vocabulary
    pass

    class Enumeration(ImmutableSet, BaseVocabulary):
    # stuff appropriate for the "closed" enumeration
    pass

    This is bad, both aesthetically and practically.
    Aesthetically, because "abstract classes stink of Java" and
    pragmatically because the __init__ from BaseVocabulary
    will generally not work for the immutable case.

    So I either have to rewrite it special, or go back in
    time and fix the original, knowing that I'm going to want
    an immutable variant.

    Again with the aesthetics, it's just ugly that I can't
    mutate an object in its __init__ and then make it immutable
    after I'm done setting it up. The approach with __new__ and
    using the superclass's __setattr__ to set values is nasty
    boilerplate-rich cruft which forces me to go back and
    completely re-implement the same functionality in a
    completely different way, just because of something that
    seems like a simple conceptual change (i.e. "don't overwrite
    or extend this thing -- make a new one if you need a
    change").

    I even tried defining __setattr__ at the end of the
    __init__, but that doesn't seem to work (or I'm doing it
    wrongly).

    Right now I'm leaning towards making a class "Immutable"
    with all the mutator methods raising NotImplementedError,
    and then subclass from this so that it overrides the
    necessary methods. It's still going to mess with me, though,
    because it will not allow the __init__ to work as planned,
    and I'll have to go back and redesign the base class to work
    with or without immutability.

    Alternatively, I could just decide to change my practice and
    implement ALL objects on the assumption that they will be
    immutable, and add *mutability* after-the-fact. But that
    seems like extraordinarily bad practice, since mutability is
    usually the better default.

    I'm going to dig through the sets module code to see how it
    does this, but what little I've seen gives me a bad feeling
    that this simple idea is hard to implement simply in Python
    -- and that strikes me as a "wart", yes.

    So, I'm wondering if there is a simple way after all.

    1) Is there an idiom for this that I just don't know?

    2) Have recent changes to the language made it easier?
    (__new__ for example, is apparently new, or at least
    newly documented -- but as I say, I'm not sure it's
    the most practical solution for this problem).

    3) Is there a "remarkably clever" way that I can tack
    on, even if it isn't exactly simple?

    and only in the unlikely event that answers 1-3 are all
    "no", would I ask:

    4) And as a last resort, if it really is hard, why?
    Shouldn't a simple idea to express in English be easy to
    express in Python? If it's really impossibly difficult,
    maybe Python should provide a means to implement it.

    Cheers,
    Terry

    --
    Terry Hancock ()
    Anansi Spaceworks http://www.AnansiSpaceworks.com
    Terry Hancock, Mar 4, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Terry Hancock

    Re: Easy immutability in python?

    Terry Hancock, Mar 4, 2006, in forum: Python
    Replies:
    2
    Views:
    275
    Alex Martelli
    Mar 4, 2006
  2. Roy Smith

    Python String Immutability Broken!

    Roy Smith, Aug 24, 2008, in forum: Python
    Replies:
    2
    Views:
    294
    Patrick Maupin
    Aug 25, 2008
  3. John Nagle

    The future of Python immutability

    John Nagle, Sep 3, 2009, in forum: Python
    Replies:
    50
    Views:
    1,223
    Steven D'Aprano
    Sep 8, 2009
  4. andrea crotti

    Immutability and Python

    andrea crotti, Oct 29, 2012, in forum: Python
    Replies:
    8
    Views:
    215
    Thomas Rachel
    Nov 8, 2012
  5. andrea crotti

    Re: Immutability and Python

    andrea crotti, Oct 29, 2012, in forum: Python
    Replies:
    0
    Views:
    167
    andrea crotti
    Oct 29, 2012
Loading...

Share This Page