how to make a variable immutable in python
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]
.
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.
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.
The problem is:
B=A
now both point to the same object.
Try:
B = [i for i in A]
now B is a new list containing all the elements from A. Or simply:
B = A[:]
Change the way you assign B
:
B = A
to
B = A[:]
精彩评论