Making immutable instances

Mike Meyer mwm at mired.org
Thu Nov 24 19:29:07 EST 2005


"Giovanni Bajo" <noway at sorry.com> writes:
> Mike Meyer wrote:
>>>> Note that this property of __slots__ is an implementation detail.
>>>> You
>>>> can't rely on it working in the future.
>>> I don't "rely" on it. I just want to catch bugs in my code.
>> I certainly hope you're not relying on it to catch bugs. You should do
>> proper testing instead. Not only will that catch pretty much all the
>> bugs you mention later - thus resolving you of the need to handcuff
>> clients of your class - it will catch lots of other bugs as well.
> My feeling is that you're trying to get too much out of my words. I'm not
> trying to handcuff anyone. You seem to concentrate on me trying to avoid people
> adding attributes to my precious objects.

Because *that's* the use case that you're preventing that I have
problems with.

> It's not that. If I write a class and want it to be immutable, it is
> because it has to be so. If I write a queue class and I say that
> people shouldn't call pop() if it's empty, I mean it. If I enforce
> it with a RuntimeError, I'm not thinking I'm handcuffing someone. I
> don't see a ImmutableError to be so different from it.

And I have no problems with that. If you believe your class should
throw an error if someone calls an instances pop() method when it's
empty, do so.

Likewise, if you want to make it so a client can't change your
attributes, feel free to do so.

However, when you prevent a client from adding an attribute, you're
not merely making your objects immutable, you're making them
static. Python isn't a static language, it's a dynamic language. I
consider parts of it that are static to be warts.

> In my view, enforcing immutability is no different from other forms of
> self-checks. Do you reckon all kind of asserts are useless then? Surely they
> don't help for anything that a good unittest couldn't uncover. But they help
> catching bugs such as breakage of invariants immediately as they happen.
> Immutability can be such an invariant.

Adding an attribute can't break an invariant. The only way an
attribute can affect an invariant is if the invariant references
it. If it references it it, then it must exist - so I can't add it.

>>>>> If it's not a wart, why would it be a wart for user-defined types
>>>>> to
>>>>> have the same behaviour?
>>>>
>>>> It's a wart because user-defined classes *don't* have the same
>>>> behavior.
>>> Then *my* solution for this would be to give user-defined classes a
>>> way to behave like builtins, eg. explicitally and fully implement
>>> immutability.
>>
>> Well, if you want to propose a change to the language, you need a good
>> use case to demonstrate the benefits of such a change. Do you have
>> such a use case? Catching bugs doesn't qualify, otherwise Python would
>> be radically different from what it is.
>
> One good reason, in my opinion, is that there *are* immutable objects in
> Python, among builtins. And people can easily build extension objects which are
> immutable. So being impossible to write a regular object in Python which is
> immutable is not orthogonal to me.

I didn't ask for a reason, I asked for a use case. Orthogonality is a
good thing, but so is generality. So I'll argue that the correct way
to make this situation orthogonal is to make builtin objects more
general by making it possible to add attributes to all of them.

On the other hand, practicality beats purity, and doing the above has
a significant cost in the current implementation, so leave it like it
is.

> Now let me ask you a question. What is a good use case for "assert" that
> justifies its introduction in the language? What is a good usecase for module
> 'unittest' which justifies its introduction in the standard library?

Unittesting doesn't change the language, and is part of any good
development methodology.

Assert is a shorthand for "if ... ; raise ...." that vanishes when you
turn on optimization. It's cleaner and more clearly expresses the
intent of the programmer, and saves a fair amount of boilerplate in
the best case.

> Why do you think tuples are immutable and *enforced* to be so?

That you can't add attributes to a tuple is a detail of the
implementation; it's true for non-immutable types as well.

>> I'm not sure it's more important than
>> things like interned strings and the sharing of small integers.  Most
>> of the discussion of immutables here seems to be caused by newcomers
>> wanting to copy an idiom from another language which doesn't have
>> immutable variables. Their real problem is usually with binding, not
>> immutability.
> I'm not such a newcomer, but (how funny) Python is *the* language that
> introduced me to the concept of immutable objects and their importance in
> design :)

Well, that would explain why you think it's so important - it's where
you first encountered it. I'd argue that it's no more important than
identity - which is what I was searching for when I talked about
interned strings sharing small integers. There are builtin types that
preserve identity for equal instances, at least under some
conditions. There are no constructs for helping you do that with
user-defined objects. Should we add them for the sake of
orthogonality? I don't think so - not without a good use case.

       <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list