Why are python strings and tuples are made immutable?

16,942

Solution 1

One is performance: knowing that a string is immutable makes it easy to lay it out at construction time — fixed and unchanging storage requirements. This is also one of the reasons for the distinction between tuples and lists. This also allows the implementation to safely reuse string objects. For example, the CPython implemenation uses pre-allocated objects for single-character strings, and usually returns the original string for string operations that doesn’t change the content.

The other 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.

https://web.archive.org/web/20201031092707/http://effbot.org/pyfaq/why-are-python-strings-immutable.htm

Solution 2

Imagine a language called FakeMutablePython, where you can alter strings using list assignment and such (such as mystr[0] = 'a')

a = "abc"

That creates an entry in memory in memory address 0x1, containing "abc", and the identifier a pointing to it.

Now, say you do..

b = a

This creates the identifier b and also points it to the same memory address of 0x1

Now, if the string were mutable, and you change b:

b[0] = 'z'

This alters the first byte of the string stored at 0x1 to z.. Since the identifier a is pointing to here to, thus that string would altered also, so..

print a
print b

..would both output zbc

This could make for some really weird, unexpected behaviour. Dictionary keys would be a good example of this:

mykey = 'abc'
mydict = {
    mykey: 123,
    'zbc': 321
}

anotherstring = mykey
anotherstring[0] = 'z'

Now in FakeMutablePython, things become rather odd - you initially have two keys in the dictionary, "abc" and "zbc".. Then you alter the "abc" string (via the identifier anotherstring) to "zbc", so the dict has two keys, "zbc" and "zbc"...

One solution to this weirdness would be, whenever you assign a string to an identifier (or use it as a dict key), it copies the string at 0x1 to 0x2.

This prevents the above, but what if you have a string that requires 200MB of memory?

a = "really, really long string [...]"
b = a

Suddenly your script takes up 400MB of memory? This isn't very good.

What about if we point it to the same memory address, until we modify it? Copy on write. The problem is, this can be quite complicated to do..

This is where immutability comes in.. Instead of requiring the .replace() method to copy the string from memory into a new address, then modify it and return.. We just make all strings immutable, and thus the function must create a new string to return. This explains the following code:

a = "abc"
b = a.replace("a", "z")

And is proven by:

>>> a = 'abc'
>>> b = a
>>> id(a) == id(b)
True
>>> b = b.replace("a", "z")
>>> id(a) == id(b)
False

(the id() function returns the memory address of the object)

Solution 3

One big advantage of making them immutable is that they can be used as keys in a dictionary. I'm sure the internal data structures used by dictionaries would get quite messed up if the keys were allowed to change.

Solution 4

Immutable types are conceptually much simpler than mutable ones. For example, you don't have to mess with copy constructors or const-correctness like in C++. The more types are immutable, the easier the language gets. Thus the easiest languages are the pure functional ones without any global state (because lambda calculus is much easier than Turing machines, and equally powerful), although a lot of people don't seem to appreciate this.

Solution 5

pros: Performance

cons: you can't change mutables.

Share:
16,942
user186477
Author by

user186477

Updated on June 08, 2022

Comments

  • user186477
    user186477 almost 2 years

    I am not sure why strings and tuples were made to be immutable; what are the advantages and disadvantage of making them immutable?

  • Kenan Banks
    Kenan Banks over 14 years
    Buuuuut you can key by any user-created object instance, which are obviously mutable. The "key" then is probably just the memory address, and if strings were mutable, you could still key by their unique memory address.
  • Matt Ellen
    Matt Ellen almost 14 years
    pros: you can't change them
  • Tommy Crush
    Tommy Crush over 10 years
    Best explanation I've heard!
  • Walter A. Aprile
    Walter A. Aprile about 9 years
    Perl does not really have strings: it has scalars, that can behave as strings or numbers (more than one type of the latter). If scalars were immutable, it would become purely functional Perl and Perl developers worldwide would commit suicide by assigning undef to themselves.
  • Dineshkumar
    Dineshkumar about 9 years
    so if i say a="abc", b="abcd" will it share abc? like b[:4] is a?
  • dbr
    dbr about 9 years
    @Dineshkumar Nope, I'm pretty sure "abc" and "abcd" are different, entirely unrelated, objects - stackoverflow.com/questions/5722006/…
  • Hejazzman
    Hejazzman about 6 years
    @Triptych which wouldn't be what you want for strings -- you'd want them to key by value, else dictionaries would be of little to no use....
  • Kenan Banks
    Kenan Banks about 6 years
    @Hejazzman that's not how python dicts work. The literal string value isn't used as the dict key, instead a hash of the string is taken. Prove this to yourself with 'abc'.__hash__().
  • Mark Ransom
    Mark Ransom about 6 years
    @Triptych everything you say is wrong. First, you could have two equal strings with different addresses so using the address doesn't work. Second while the hash of a string is used by the dict, it's the string itself that is the key - prove it by showing d.keys(). You could easily have two strings with the same hash and the dict will keep them separate.
  • Kenan Banks
    Kenan Banks about 6 years
    @Mark Ransom Not address, hash. By definition, you cannot have two strings which compare as equal but which have different hashes.
  • Mark Ransom
    Mark Ransom about 6 years
    @Triptych your very first comment from 8 years ago was about memory addresses, but I never responded at the time. You're correct that you can't have same strings with different hashes, but you can have different strings with same hash! The hash is not sufficient by itself as a key, it's just part of the mechanics.
  • Hejazzman
    Hejazzman about 6 years
    @Triptych I know how Python dicts work (or hashmaps in general in any language). That was not my point. My point being that the same string should be able to point back to the same entry, which for mutable strings (and their "unique memory address" as the key in the hashmap) would not be the case. You would then need to have the exact same string pointer, and not just the same string contents to get back an entry from a dictionary.
  • aCuria
    aCuria over 4 years
    This does not explain why tuples are immutable
  • flow2k
    flow2k over 3 years
    @dbr You say "Copy on write... can be quite complicated to do.." But isn't implementing immutability just as complicated? You'd still need to be aware if modifications are made, and if so, make another "instance" with the desired modifications.
  • antonagestam
    antonagestam about 3 years
    The link to effbot is dead, maybe replace with an internet archive link? web.archive.org/web/20201031092707/http://effbot.org/pyfaq/…
  • Mark Ransom
    Mark Ransom almost 2 years
    @flow2k no immutability is easier. Python knows which operations can modify a string, and it forces all of them to create a new string object - even if that string is identical to the one you started with.