0

It seems counter intuitive that two orthogonal concepts like mutability and type are entangled instead of having some way of mutable qualifying types, like in other languages.

Wouldn't it benefit performance if strings and numbers could be mutable by choice and perform replacements and arithmetic/bit operations in place instead of creating a new object for the result every time?

It occurred to me that maybe it is that way (immutable strings and numbers) to promote functional style programming, but Python is not meant to be a functional programming language.

This question is not about what is mutability/immutability or their pros and cons.

imreal
  • 10,178
  • 2
  • 32
  • 48
  • https://docs.python.org/2/faq/design.html#why-are-python-strings-immutable – Martijn Pieters Dec 15 '14 at 21:30
  • All variables are mutable in Python; some datatypes are mutable "in-place", and some not. The ones that are not mutable "in-place" are called "hashable", and can be used for things like dictionary keys. – Paulo Scardine Dec 15 '14 at 21:31
  • 4
    @PauloScardine I think you misunderstand the definition of "mutable". – Mark Ransom Dec 15 '14 at 21:34
  • The value of an immutable container object that contains a reference to a mutable object can change when the latter’s value is changed; however the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value, it is more subtle. – Mazdak Dec 15 '14 at 21:37
  • @MarkRansom I think the OP is thinking about `const` keyword from some languages. In this sense, there is no immutable variables in Python, just immutable instances. – Paulo Scardine Dec 15 '14 at 21:37
  • @PauloScardine I do understand the difference of intent and implementation between `const` and immutable. But I am still confused about why mutability is intrinsic to the type. – imreal Dec 15 '14 at 21:42
  • 1
    @imreal all variables in Python are like pointers; for some objects there is a guarantee that the value you are referencing will not change behind your back, those are called "immutable". The language designers chose to tie this guarantee to the type and not to the instance (for example, by having a `const` keyword). – Paulo Scardine Dec 15 '14 at 21:48

2 Answers2

4

Mutability/immutability is not just a performance matter. Mutating an object means that all references to the object see the change. For some types, this would lead to very odd behavior:

def function(number_of_items):
     n = number_of_items
     # do some stuff. . .
     n -= 1
     # now the variable number_of_items was changed in the enclosing scope!

Such behavior already suprises some people when it comes to mutable types like lists, but it would be even more surprising for numeric types, since people expect that, e.g., the number 3 cannot change its value.

Moreover, immutability (or at least immutability of the hash-relevant data) is necessary for hashability. Being able to mutate strings would mean you could no longer use them as dictionary keys. You could say that only immutable strings could be used as dictionary keys, but that in effect creates a type split.

The duck-typing philosophy of Python means types are basically defined by what they do. If two objects differ in something as basic as mutability, you can't really use them the same way, so it doesn't make sense to consider them the same type, even if they nominally are. Likewise, there is little practical difference between having one type with mutable and immutable variants, versus having two types that vary in mutability --- e.g., having mutable and immutable lists vs having list and tuple as separate types.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • See also the dreaded "mutable default argument" gotcha. http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – theodox Dec 15 '14 at 21:42
2

It makes no sense to have a type produce mutable or immutable instances. Their behaviour would radically change; half the methods would no longer work, and it makes it much harder to apply optimisations.

You are free to create your own types that allow mutation in some cases, are immutable in others, but the built-in types make use of specific optimisations and core Python functionality counts on objects being truly immutable, not based on programmer preference.

The programmer is free to switch between types; bytes vs. bytearray, tuple vs. list, frozenset vs. set, where it makes sense.

The Python FAQ addresses why strings are immutable:

Why are Python strings immutable?

There are several advantages.

One is performance: knowing that a string is immutable means we can allocate space for it at creation time, and the storage requirements are fixed and unchanging. This is also one of the reasons for the distinction between tuples and lists.

Another advantage is that strings in Python are considered as “elemental” as numbers. No amount of activity will change the value 8 to anything else, and in Python, no amount of activity will change the string “eight” to anything else.

Add to this that dictionaries and sets use hash tables, an algorithm that requires that keys are immutable for locating keys by their value alone.

From the same FAQ again:

Why must dictionary keys be immutable?

The hash table implementation of dictionaries uses a hash value calculated from the key value to find the key. If the key were a mutable object, its value could change, and thus its hash could also change. But since whoever changes the key object can’t tell that it was being used as a dictionary key, it can’t move the entry around in the dictionary. Then, when you try to look up the same object in the dictionary it won’t be found because its hash value is different. If you tried to look up the old value it wouldn’t be found either, because the value of the object found in that hash bin would be different.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    I understand the advantages of an object being immutable, my question is why is it determined by the type instead of allowing the programmer to choose? – imreal Dec 15 '14 at 21:33
  • 1
    @imreal: the programmer can choose the type too. You are free to use a `list` vs. a `tuple`, or a `set` vs. a `frozenset`. In Python 3 you also have `bytes` vs. `bytearray`. – Martijn Pieters Dec 15 '14 at 21:33
  • @imreal are you mixing immutable variables (like `const` in some languages) with type immutability? – Paulo Scardine Dec 15 '14 at 21:35
  • @MartijnPieters - I think the OP is asking why Python has nothing like `const` in C++. In which case, I refer him to http://stackoverflow.com/q/17291791/2555451 and http://stackoverflow.com/questions/2682745/creating-constant-in-python. Summarized, the designers of Python simply didn't want to include `const`. They made mutability determined by type to keep things simple and consistent. –  Dec 15 '14 at 21:35