Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to make a variable immutable in python

Tags:

python

list

My python script:

N = 2  # 2*2 matrix

a = N * [0]
b = a

print(b)  # prints [0, 0]

for i in range(N):
    a[i] = N * [0]

for i in range(N):
    for j in range(N):
        a[i][j] = 0

print(a)  # prints [[0, 0], [0, 0]]

print(b)  # prints [[0, 0], [0, 0]]

Why does my second print(b) change? How to make it immutable? I'd like my b to still contain [0, 0].

like image 221
Egy Mohammad Erdin Avatar asked Apr 01 '11 08:04

Egy Mohammad Erdin


People also ask

How do you make a value immutable in Python?

All you have to do is sub-class from Freezer . After initialization of the Python, I “freeze” the object with my overriding of the __delattr__ and __setattr__ methods on the object. I set _frozen = True which indicates the instance is now “frozen”. objects become immutable.

Are variable immutable in Python?

In python, some variables can change their value after creation while some cannot. Therefore, if a variable can change its value it is mutable in nature. Otherwise, if it cannot change its value after creation it is immutable in nature.


2 Answers

Your understanding of "objects" in Python and variable assignments is flawed.

In a language like C, when you define a variable (say int a), a tiny area of memory is allocated and reserved for this variable and a is now something that refers to this area of memory. You can poke into this area, change it and find that a "has a" different value now. A statement like a = 2 (or a = b where b is another variable) takes the value of the right hand side and writes it into the memory location reserved for a. Now you can modify b as you wish but a will still retain the original value. This is why you can do things like a++ in C which means, "get the value of what a refers to, add one to it and write it back to the same location".

In Python, when you say x = [], a new list object is created and x is made to "point" to that list. Now any change you make to x is affecting this object. Suppose you say y = x, you will get another reference to the same object. Changing y (or x for that matter) will change the object which is now pointed to by x and y. This is what you've done with the B = A assignment. All things done to this object via A will be visible when you access it via B since they both point to the same object. In this sense, all variables in Python are like pointers in C. You can also understand why we don't have a ++ operator in Python since it's meaningless to modify the contents of a memory location like in C.

The solution suggested by others so far is suggesting that you make a new object with the exact same contents as the list pointed to by A and make B point to this copy. This way, if you modify A (or what A points to), B (or what B points to) will remain unchanged.

This however doesn't make B "immutable" (i.e. an object which cannot be modified in place). However, I think you have simply used the word erroneously and meant that you didn't want the aliasing to take place.

like image 151
Noufal Ibrahim Avatar answered Nov 01 '22 13:11

Noufal Ibrahim


When assigning objects in python, you assign references (something like pointers in C).

There are several ways to circumvent this but the IMHO most idiomatic is using copy:

import copy
B = copy.copy(A)

In some cases you even may want to used deepcopy(), have a look at the documentation for details.

like image 41
hynek Avatar answered Nov 01 '22 12:11

hynek