3

I am trying to figure out whether the following are immutable in Sage (which is built on Python so I believe if it is immutable in python, I believe in most cases it will be immutable in Sage)

Below are objects e, f, g, i

class e: pass
f = e()
g = pi # (g's "type" in Sage is symbolic expression. It's supposed to be 3.1415....etc)
i = lambda x: x*x

I gather that e is a class which means it is mutable (Does an immutable class make sense? Can't all classes be modified?). Since f is an instance of a class, I am guessing it is also mutable since classes are mutable.

Since numbers are immutable in Python, g should be immutable as well since it is a number despite being irrational

Finally i is a function which means it should be mutable?

I'm not quite sure I understand that concept of immutability. What would it mean for a function to be immutable? For a class to be immutable?

metamatt
  • 13,809
  • 7
  • 46
  • 56
imres
  • 41
  • 1
  • 3

2 Answers2

7

e is mutable. You can, for instance, add a new method on the class: e.foo = lambda self,x: x.

f is mutable. You can, for instance, add a new field to this class instance: f.x = 99.

g is immutable. You can't change anything about it.

i is not immutable. You can do all sorts of evil things to it: i.func_code = (lambda x: 123).func_code after which i(10) will be 123 instead of 100. (You can also do more reasonable things to it. After i.__doc__ = "This function returns the square of its argument." you will get a more helpful result from help(i).)

An object is mutable if there's something you can do to the object that changes its possible future behaviour. You can't change the behaviour of 10; you can change the behaviour of a function object, or a class, or a class instance, or a list. (But not a tuple. Once a tuple is made, it stays just as it is for as long as it exists.)

Gareth McCaughan
  • 19,888
  • 1
  • 41
  • 62
  • The comment about tuples is really only true when everything the tuple references is also immutable. – ncoghlan Apr 14 '11 at 05:44
  • Hmmmm, kinda. Changing something else referenced by the tuple isn't really doing something *to the tuple*. But I take your point. – Gareth McCaughan Apr 20 '11 at 21:48
  • Interestingly, the definition in the docs aligns with your explanation (i.e. tuples are officially considered immutable, even though their value can change over time): http://docs.python.org/reference/datamodel.html – ncoghlan Apr 21 '11 at 01:34
  • If I were going to be all computersciencey about it I'd suggest that we really want two notions of immutability -- call them "locally immutable" and "transitively immutable" or something -- where the first means "nothing you do directly to the object changes its behaviour" and the second is equivalent to both of (1) "the object is locally immutable and so is everything reachable from it" and (2) "nothing you do using the object changes its behaviour". – Gareth McCaughan Apr 21 '11 at 08:59
  • Yeah, rereading the definitions in the Python docs reminded me just how tricky it can be to draw a clean line between them once you start considering the "it depends on what you mean by immutable" corner cases. – ncoghlan Apr 21 '11 at 16:57
3

Formally? An object is mutable if it can change value without changing identity.

Lists are mutable, so the value of a particular instance can change over time:

>>> x = orig_x = []
>>> x == []
True
>>> x += [1]
>>> x == []      # The value of x has changed
False
>>> x is orig_x  # But the identity remains the same
True

Numbers are immutable, however, so their value can't change. Instead, the variable has to be updated to refer to a completely different object:

>>> x = orig_x = 1
>>> x == 1
True
>>> x += 1
>>> x == 1        # Again, the value of x has changed
False
>>> x is orig_x   # But now the identity has changed as well
False

Immutability is an important concept, since knowing that an object's value can't change lets you make certain assumptions about it (for example, dict effectively requires immutable keys and set and frozenset require immutable members, as the value of an object affects how it should be stored in the data structure. If mutable entries were permitted, they may end up being in the wrong place if they are modified after being stored)

Contrary to popular belief, user defined classes that don't override the definition of equality are technically immutable. This is because the default definition of the "value" of a user defined class is just id(self). When an object's value is its identity, there is obviously no way for them to differ over time, and hence the object doesn't quality as "mutable".

Informally? Most people use an intuitive "Can I change it?" definition along the lines of Gareth McCaughan's answer. It's the same basic idea as the formal definition, just using a broader meaning of the term "value" than the technical definition in terms of equality checks.

ncoghlan
  • 40,168
  • 10
  • 71
  • 80
  • Strictly speaking, `dict`/`set`/`frozenset` only enforce a requirement that an object be hashable rather than completely immutable. You can get seriously weird behaviour if your keys/elements aren't truly immutable, though. – ncoghlan Apr 14 '11 at 04:41
  • Also see the introduction in: http://docs.python.org/reference/datamodel.html. As that intro points out, the boundary between mutable and immutable can get a little fuzzy at times. – ncoghlan Apr 21 '11 at 01:36