Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #32383 > unrolled thread

Immutability and Python

Started byandrea crotti <andrea.crotti.0@gmail.com>
First post2012-10-29 15:20 +0000
Last post2012-11-08 08:38 +0100
Articles 9 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  Immutability and Python andrea crotti <andrea.crotti.0@gmail.com> - 2012-10-29 15:20 +0000
    Re: Immutability and Python Paul Rubin <no.email@nospam.invalid> - 2012-10-29 08:55 -0700
      Re: Immutability and Python Chris Angelico <rosuav@gmail.com> - 2012-10-30 03:08 +1100
      Re: Immutability and Python andrea crotti <andrea.crotti.0@gmail.com> - 2012-10-29 16:33 +0000
    Re: Immutability and Python Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-10-29 23:02 +0000
    Re: Immutability and Python rusi <rustompmody@gmail.com> - 2012-10-30 09:22 -0700
      Re: Immutability and Python Neal Becker <ndbecker2@gmail.com> - 2012-10-30 16:45 -0400
        Re: Immutability and Python rusi <rustompmody@gmail.com> - 2012-10-30 20:21 -0700
    Re: Immutability and Python Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2012-11-08 08:38 +0100

#32383 — Immutability and Python

Fromandrea crotti <andrea.crotti.0@gmail.com>
Date2012-10-29 15:20 +0000
SubjectImmutability and Python
Message-ID<mailman.3018.1351524004.27098.python-list@python.org>
I have a philosofical doubt about immutability, that arised while doing
the SCALA functional programming course.

Now suppose I have a simple NumWrapper class, that very stupidly does:

class NumWrapper(object):
    def __init__(self, number):
        self.number = number

and we want to change its state incrementing the number, normally I
would do this

    def increment(self):
        self.number += 1


But the immutability purists would instead suggest to do this:

    def increment(self):
        return NumWrapper(self.number + 1)


Now on one hand I would love to use only immutable data in my code, but
on the other hand I wonder if it makes so much sense in Python.

My impression is that things get more clumsy in the immutable form, for
example in the mutable form I would do simply this:

number = NumWrapper(1)
number.increment()

while with immutability I have to do this instead:
new_number = number.increment()

But more importantly normally classes are way more complicated than my
stupid example, so recreating a new object with the modified state might
be quite complex.

Any comments about this? What do you prefer and why?

[toc] | [next] | [standalone]


#32388

FromPaul Rubin <no.email@nospam.invalid>
Date2012-10-29 08:55 -0700
Message-ID<7xsj8xl1ct.fsf@ruckus.brouhaha.com>
In reply to#32383
andrea crotti <andrea.crotti.0@gmail.com> writes:
> and we want to change its state incrementing the number ...
>  the immutability purists would instead suggest to do this:
>     def increment(self):
>         return NumWrapper(self.number + 1)

Immutability purists would say that numbers don't have "state" and if
you're trying to change a number's state by incrementing it, that's not
immutability.  You end up with a rather different programming style than
imperative programming, for example using tail recursion (maybe wrapped
in an itertools-like higher-order function) instead of indexed loops to
iterate over a structure.

[toc] | [prev] | [next] | [standalone]


#32390

FromChris Angelico <rosuav@gmail.com>
Date2012-10-30 03:08 +1100
Message-ID<mailman.3024.1351526914.27098.python-list@python.org>
In reply to#32388
On Tue, Oct 30, 2012 at 2:55 AM, Paul Rubin <no.email@nospam.invalid> wrote:
> andrea crotti <andrea.crotti.0@gmail.com> writes:
>> and we want to change its state incrementing the number ...
>>  the immutability purists would instead suggest to do this:
>>     def increment(self):
>>         return NumWrapper(self.number + 1)
>
> Immutability purists would say that numbers don't have "state" and if
> you're trying to change a number's state by incrementing it, that's not
> immutability.  You end up with a rather different programming style than
> imperative programming, for example using tail recursion (maybe wrapped
> in an itertools-like higher-order function) instead of indexed loops to
> iterate over a structure.

In that case, rename increment to next_integer and TYAOOYDAO. [1]
You're not changing the state of this number, you're locating the
number which has a particular relationship to this one (in the same
way that GUI systems generally let you locate the next and previous
siblings of any given object).

ChrisA
[1] "there you are, out of your difficulty at once" - cf WS Gilbert's "Iolanthe"

[toc] | [prev] | [next] | [standalone]


#32392

Fromandrea crotti <andrea.crotti.0@gmail.com>
Date2012-10-29 16:33 +0000
Message-ID<mailman.3026.1351528391.27098.python-list@python.org>
In reply to#32388
2012/10/29 Chris Angelico <rosuav@gmail.com>:
> On Tue, Oct 30, 2012 at 2:55 AM, Paul Rubin <no.email@nospam.invalid> wrote:
>> andrea crotti <andrea.crotti.0@gmail.com> writes:
>>> and we want to change its state incrementing the number ...
>>>  the immutability purists would instead suggest to do this:
>>>     def increment(self):
>>>         return NumWrapper(self.number + 1)
>>
>> Immutability purists would say that numbers don't have "state" and if
>> you're trying to change a number's state by incrementing it, that's not
>> immutability.  You end up with a rather different programming style than
>> imperative programming, for example using tail recursion (maybe wrapped
>> in an itertools-like higher-order function) instead of indexed loops to
>> iterate over a structure.
>
> In that case, rename increment to next_integer and TYAOOYDAO. [1]
> You're not changing the state of this number, you're locating the
> number which has a particular relationship to this one (in the same
> way that GUI systems generally let you locate the next and previous
> siblings of any given object).
>
> ChrisA
> [1] "there you are, out of your difficulty at once" - cf WS Gilbert's "Iolanthe"
> --
> http://mail.python.org/mailman/listinfo/python-list


Yes the name should be changed, but the point is that they are both
ways to implement the same thing.

For example suppose I want to have 10 objects (for some silly reason)
that represent the next number, in the first case I would do:

numbers = [NumWrapper(orig.number)] * 10
for num in numbers:
    num.increment()

while in the second is as simple as:
numbers = [orig.next_number()] * 10

composing things become much easier, but as a downside it's not always
so easy and convienient to write code in this way, it probably depends
on the use case..

[toc] | [prev] | [next] | [standalone]


#32438

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-10-29 23:02 +0000
Message-ID<508f0b0e$0$29967$c3e8da3$5496439d@news.astraweb.com>
In reply to#32383
On Mon, 29 Oct 2012 15:20:02 +0000, andrea crotti wrote:

> I have a philosofical doubt about immutability, that arised while doing
> the SCALA functional programming course.

"Philosophical". Like most words derived from the ancient Greeks, the "F" 
sound uses "ph" rather than "f".


> Now suppose I have a simple NumWrapper class, that very stupidly does:
> 
> class NumWrapper(object):
>     def __init__(self, number):
>         self.number = number
> 
> and we want to change its state incrementing the number, normally I
> would do this
> 
>     def increment(self):
>         self.number += 1

That's a perfectly fine (although incomplete) design for a mutable 
numeric class. But as the basis of an immutable class, it's lousy.

> But the immutability purists would instead suggest to do this:
> 
>     def increment(self):
>         return NumWrapper(self.number + 1)

Only if they don't know Python very well :-)

In this example, the right way to get an immutable class is:

class NumWrapper(int):  # not exactly a *wrapper*
    def increment(self):
        return self.__class__(self + 1)


and you're done. Immutability for free, because you don't store state 
anywhere that pure-Python code can get to it. (Technically, using ctypes 
you could mutate it, so don't do that.)

Here's a sketch of another technique:

class MyNum(object):
    __slots__ = '_num'
    def __new__(cls, arg):
        instance = object.__new__(cls)
        instance._num = int(arg)
        return instance
    @property
    def value(self):
        return self._num
    def increment(self):
        return self.__class__(self.value + 1)


> Now on one hand I would love to use only immutable data in my code, but
> on the other hand I wonder if it makes so much sense in Python.

You can go a long, long way using only immutable primitives and 
functional style in Python, and I recommend it.

On the other hand, a *purely* functional approach doesn't make a lot of 
sense for some tasks. Python is not a pure functional language, and 
doesn't force you to hammer round pegs into the square hole of the 
functional style.

Some problems are best modelled by an object that holds state and can 
change over time, e.g. a database or a dict. Other problems are best 
modelled by constants which do not change, but can be replaced by other 
constants, e.g. numbers. Some problems fall into a grey area, e.g. lists, 
arrays, sets, sequences, strings.

My advice is to always be alert for square pegs in your code, and write 
them in functional style using immutable instances, but don't be a 
purist. If you have a round peg, write that part of your code using a 
mutable instance with in-place mutator methods, and be happy.

The beauty of Python is that you can use whichever style suits the 
problem best.


> My impression is that things get more clumsy in the immutable form, for
> example in the mutable form I would do simply this:
> 
> number = NumWrapper(1)
> number.increment()
> 
> while with immutability I have to do this instead: 
> new_number = number.increment()

Why is this clumsy? Do you have problems with this?

x = 1
y = x+1



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#32499

Fromrusi <rustompmody@gmail.com>
Date2012-10-30 09:22 -0700
Message-ID<526d3d06-f9b8-49b3-a0e8-f18ac3b6488e@ah9g2000pbd.googlegroups.com>
In reply to#32383
On Oct 29, 8:20 pm, andrea crotti <andrea.crott...@gmail.com> wrote:
<snipped>
> Any comments about this? What do you prefer and why?

Im not sure how what the 'prefer' is about -- your specific num
wrapper or is it about the general question of choosing mutable or
immutable types?

If the latter I would suggest you read
http://en.wikipedia.org/wiki/Alexander_Stepanov#Criticism_of_OOP

[And remember that Stepanov is the author of C++ STL, he is arguably
as important in the C++ world as Stroustrup]

[toc] | [prev] | [next] | [standalone]


#32502

FromNeal Becker <ndbecker2@gmail.com>
Date2012-10-30 16:45 -0400
Message-ID<mailman.3101.1351629946.27098.python-list@python.org>
In reply to#32499
rusi wrote:

> On Oct 29, 8:20 pm, andrea crotti <andrea.crott...@gmail.com> wrote:
> <snipped>
>> Any comments about this? What do you prefer and why?
> 
> Im not sure how what the 'prefer' is about -- your specific num
> wrapper or is it about the general question of choosing mutable or
> immutable types?
> 
> If the latter I would suggest you read
> http://en.wikipedia.org/wiki/Alexander_Stepanov#Criticism_of_OOP
> 
> [And remember that Stepanov is the author of C++ STL, he is arguably
> as important in the C++ world as Stroustrup]

The usual calls for immutability are not related to OO.  They have to do with 
optimization, and specifically with parallel processing.

[toc] | [prev] | [next] | [standalone]


#32514

Fromrusi <rustompmody@gmail.com>
Date2012-10-30 20:21 -0700
Message-ID<c2273c0f-ec84-441a-acdf-10f97d24b976@i7g2000pbf.googlegroups.com>
In reply to#32502
On Oct 31, 1:45 am, Neal Becker <ndbeck...@gmail.com> wrote:
> rusi wrote:
> > On Oct 29, 8:20 pm, andrea crotti <andrea.crott...@gmail.com> wrote:
> > <snipped>
> >> Any comments about this? What do you prefer and why?
>
> > Im not sure how what the 'prefer' is about -- your specific num
> > wrapper or is it about the general question of choosing mutable or
> > immutable types?
>
> > If the latter I would suggest you read
> >http://en.wikipedia.org/wiki/Alexander_Stepanov#Criticism_of_OOP
>
> > [And remember that Stepanov is the author of C++ STL, he is arguably
> > as important in the C++ world as Stroustrup]
>
> The usual calls for immutability are not related to OO.  They have to do with
> optimization, and specifically with parallel processing.

From the time of Backus' Turing award
http://www.thocp.net/biographies/papers/backus_turingaward_lecture.pdf
it is standard fare that
assignment = imperative programming (which he collectively and
polemically called the von Neumann bottleneck)
That what he decried as 'conventional programming languages' today
applies to OO languages; see
http://www.cs.tufts.edu/~nr/backus-lecture.html

A more modern viewpoint:

--------------
Object-oriented programming is eliminated entirely from the
introductory curriculum, because it is both anti-modular and anti-
parallel by its very nature, and hence unsuitable for a modern CS
curriculum.  A proposed new course on object-oriented design
methodology will be offered at the sophomore level for those students
who wish to study this topic.
----------------

from http://existentialtype.wordpress.com/2011/03/15/teaching-fp-to-freshmen/

Call it polemical if you like; noting that that's Carnegie Mellon.

[toc] | [prev] | [next] | [standalone]


#32935

FromThomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de>
Date2012-11-08 08:38 +0100
Message-ID<k7fni3$oml$1@r03.glglgl.gl>
In reply to#32383
Am 29.10.2012 16:20 schrieb andrea crotti:

> Now on one hand I would love to use only immutable data in my code, but
> on the other hand I wonder if it makes so much sense in Python.

You can have both. Many mutable types distinguish between them with 
their operators.

To pick up your example,


class NumWrapper(object):
     def __init__(self, number):
         self.number = number
     def __iadd__(self, x):
         self.number += x
         return self
     def __add__(self, x):
         return NumWrapper(self.number + x)

So with

     number += 1

you keep the same object and modify it, while with

     number = number + 1

or

     new_number = number + 1

you create a new object.


> But more importantly normally classes are way more complicated than my
> stupid example, so recreating a new object with the modified state might
> be quite complex.
>
> Any comments about this? What do you prefer and why?

That's why I generally prefer mutable objects, but it can depend.


Thomas

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web