Not all python objects are created equal. Some objects are mutable, meaning they can be altered, while others are immutable; pretty much the opposite of mutable🙂. So what does this mean for you when writing code in python? This post will talk about (a) the mutability of common data types and (b) instances where mutability matters.
Mutability of Common Types
The way I like to remember which types are mutable and which are not is that containers and user-defined types are generally mutable while everything else is immutable. Then I just remember the exceptions like tuple which is an immutable container and frozen set which is an immutable version of set (which makes sense, so you just have to remember tuple).
The following are immutable objects:
- Numeric types: int, float, complex
- string
- tuple
- frozen set
- bytes
The following objects are mutable:
- list
- dict
- set
- byte array
What if I need a mutable string to do something like character swapping? Well then use a byte array.
When Mutability Matters
Mutability might seem like an innocuous topic, but when writing an efficient program it is essential to understand. For instance, the following code is a straightforward solution to concatenate a string together:
string_build = "";
for data in container:
string_build += str(data)
But in reality, it is extremely inefficient. Because strings are immutable, concatenating two strings together actually creates a third string which is a combination of the previous two. If you are iterating a lot and building a large string, you will waste a lot of memory creating and throwing away objects. Also, do not forget that nearing the end of the iteration you will be allocating and throwing away very large string objects which is even more costly.
The following is a more efficient and pythonic method:
builder_list = []
for data in container:
builder_list.append(str(data))
"".join(builder_list)
### Another way is to use a list comprehension
"".join([str(data) for data in container])
### or use the map function
"".join(map(str, container))
This code takes advantage of the mutability of a single list object to gather your data together and then allocate a single result string to put your data in. That cuts down on the total number of objects allocated by almost half.
Another gotcha related to mutability is this little number:
def my_function(param=[]):
param.append("thing")
return param
What you might think would happen is that by giving an empty list as a default value to param, a new empty list is allocated each time the function is called and no list is passed in. But what actually happens is that every call that uses the default list will be using the same list. This is because Python (a) only evaluates functions definitions once, (b) evaluates default arguments as part of the function definition, and (c) allocates one list (a mutable object) for every call of that function. See the following example:
print(my_function()) # prints: ["thing"] print(my_function()) # prints: ["thing", "thing"]
Do not put a mutable object as the default value of a function parameter. Immutable types are perfectly safe. If you want to get the intended effect, do this.
def my_function2(param=None):
if param is None:
param = []
param.append("thing")
return param
Conclusion
Mutability matters. Learn it. Primitive-like types are probably immutable. Container-like types are probably mutable.
[…] Source: Python Objects: Mutable vs. Immutable […]
[…] Source: Python Objects: Mutable vs. Immutable […]
[…] codehabitude stackoverflow-1 stackoverflow-2 stackoverflow-3 […]
[…] lets follow some code snippets in the link mutable/non-mutable […]
[…] ejemplo de mutabilidad que encontré en un post cuando buscaba sobre el tema fue sobre […]
[…] duplicates of elements.) [For more information on mutable and immutable data types please visit THIS site] How to create a set is quite straightforward. This is done as […]
[…] 如果你执行id(foo)和id(bar),就会看到结果是一样的。如果没有正确地理解这种一致性就可能会导致出人意料的程序漏洞,特别是对于像列表这样的可变数据结构。 […]
How can the sets be mutable in python ? Can you please explain with an example ?
Sure. Sets in Python are mutable because they can be modified in place. For instance, you can add elements to a set:
a = set('1')
a.add('2')
print(a) # a contains 1 and 2
A set has many methods that allow it to be modified: e.g. add, update, clear, pop, remove.
In contrast, a frozenset is immutable and does not have methods that allow modification:
a = frozenset('1')
a.add('2') # throws an error
Thanks,that explains it well. But can we replace the contents in a set, as we do with a list or dictionary ?
Yes, that is what makes it mutable.