[Python-ideas] immutable classes [was: pre-PEP: Default Argument Expressions]

Jim Jewett jimjjewett at gmail.com
Sun Feb 18 04:18:53 CET 2007


I have added python-ideas to the Cc list, and suggest removing
python-3000 from additional replies.

BJörn Lindqvist gave an example explaining why he might want to
re-evaluate mutable default arguments.  It still looks like like buggy
code, but it isn't the error I was expecting -- and I think it comes
from the difficulty of declaring something immutable.

On 2/15/07, BJörn Lindqvist <bjourne at gmail.com> wrote:
> On 2/15/07, Jim Jewett <jimjjewett at gmail.com> wrote:

> > Then are there *any* good use cases for [non-persistent mutable defaults]

> > (1)  Not really (treated as) mutable.  ==> Doesn't care

> >     >>> def f(extra_settings={}) ...

> > usually doesn't modify or even store extra_settings;  ...

> That is dangerous code. Sooner or later someone will modify the
> extra_settings dict.

How?

    >>> f.func_defaults[0]['key']=value

may be misguided, but it probably isn't an accident.

BJörn's example does store the mutable directly, but it makes a bit
more sense because it looks like a complex object rather than just a
mapping.

>     class Vector:
>         def __init__(self, x, y, z):
>             self.x = x
>             self.y = y
>             self.z = z

>     class Ray:
>         def __init__(self, direction, origin = Vector(0, 0, 0)):
>             self.direction = direction
>             self.origin = origin
>
>     ray1 = Ray(Vector(0, 0, -1))
>     ray2 = Ray(Vector(0, 0, 1))
>     ray3 = Ray(Vector(-1, 0, 0), Vector(2, 3, 4))

> The above code looks quite nice, but is wrong.

Why is vector mutable?

Is the real problem that it is too hard to declare objects or
attributes immutable?

My solution is below, but I'll grant that it isn't as straightforward
as I would have liked.  Is this something that could be solved with a
recipe, or a factory to make immutable classes?

>>> class Vector3D(tuple):
...         def __new__(self, x, y, z):
...             return super(Vector3D, self).__new__(self, (x, y, z))
...         x=property(lambda self: self[0])
...         y=property(lambda self: self[1])
...         z=property(lambda self: self[2])

-jJ



More information about the Python-ideas mailing list