0

I am doing a simple test to verify mutability I have a variable var

I want to verify that = assignment operator changes the value at same memory location for it I a doing

var = 1

To print address of var I do

hex(id(var)) it gives me '0x1b65158' then I assign new value var = 2 but now hex(id(var)) is changed to '0x1b65140' if it is changing the same location it should be return same isnt it? please explain

Note : I dont want to do same assignment mentioned here. I am trying to understand how it is assigning mutably. And I am not trying to create constant here.

Yugandhar Chaudhari
  • 3,831
  • 3
  • 24
  • 40

2 Answers2

5

Some implementations of Python keep an array of integer objects for all integers between -5 and 256. Meaning that when you create an int in that range you actually just get back a reference to the existing object.

For example:

id(1)
--> 8790876942080
x = 1
id(x)
--> 8790876942080

So, when you assign a new values 1 or 2 to your variable, you actually assign the reference to these exisiting objects.

This behaviour, as I mentioned above, is not consistent for all integers, for example:

id(5555555555)
--> 89108592
x = 5555555555
id(x)
--> 89109104

You can read more here:

  1. ID Function

  2. is Operator

Tim Mironov
  • 849
  • 8
  • 22
  • so do you know how can I cross verify that assignment operator modifies the value at same memory location – Yugandhar Chaudhari Jul 25 '19 at 09:20
  • @YugandharChaudhari, I think the concept of the value "sitting" in some memory location can be a little misleading. I find the answer Georgy provided in the first comment as especially helpful here, I'm quoting from there: 'In Python—unlike, say, C—a variable is not a location where values live. It's just a name. The values live wherever they want to.1 So, when you do this: a = 10 b = a You're not making b into a reference to a. That idea doesn't even make sense in Python. You're making a into a name for 10, and then making b into another name for 10.' – Tim Mironov Jul 25 '19 at 12:59
  • so they are just like tags or labels here right? so what do name actually hold address of 10? – Yugandhar Chaudhari Jul 25 '19 at 13:06
2

This may help you understand what is going on:

In [1]: hex(id(1))                                                                                                                                                                  
Out[1]: '0x109af50a0'

In [2]: hex(id(2))                                                                                                                                                                  
Out[2]: '0x109af50c0'

In [3]: var = 1                                                                                                                                                                     

In [4]: hex(id(var))                                                                                                                                                                
Out[4]: '0x109af50a0'

In [5]: var = 2                                                                                                                                                                     

In [6]: hex(id(var))                                                                                                                                                                
Out[6]: '0x109af50c0'

Notice that the id follows the value and not the variable.

It might also be helpful to look at the documentation for the id built-in:

id(object)

Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

CPython implementation detail: This is the address of the object in memory.

When we write something like hex(id(var)) we are asking for the hexadecimal version of the address of the object stored in var.

If we want to test if var is immutable, our only option is to attempt to assign something to it and check if an exception occurs.

In fact, it is impossible to declare a variable that cannot be changed in Python. The closest you can get is to declare an instance of a class that throws an exception if you try to assign a value to its properties. For more information on that, see this question:

How do I create a constant in Python?

  • so is there any way I can test the mutability of location? – Yugandhar Chaudhari Jul 25 '19 at 09:19
  • If an attempt to assign to a variable raises an exception, it may be immutable. You would have to examine the exception. –  Jul 25 '19 at 10:15
  • that is the test for immutability – Yugandhar Chaudhari Jul 25 '19 at 10:53
  • Yes. If an attempt to assign to a variable *does not* raise an exception, then it is mutable. I feel like I am pointing out the obvious here. –  Jul 25 '19 at 10:58
  • nope it does not necessarily have to do so .. it may simply allocate to another location and rebind to it.. – Yugandhar Chaudhari Jul 25 '19 at 11:06
  • Maybe you should give me your definitions of "variable" and "mutable", because I really don't understand you. Maybe this question will help you: https://stackoverflow.com/questions/2682745/how-do-i-create-a-constant-in-python –  Jul 25 '19 at 11:41
  • yes in erlang you cant do x =1 to x=2 raises error as you said but in elixir if you see X=1 you can do to X=2 even if it is completely immutable in nature.. so they call it rebinding it does not change at memory location ever.. coming back to OOP language where they allow mutable state.. I was expecting it will hold the same location after change.. but as @ItamarMushkin pointed..int is immutable here.. if we try with mutable data structure like list / dict it gives the same address... hope it helps to understand you – Yugandhar Chaudhari Jul 25 '19 at 12:10
  • @YugandharChaudhari You are confusing "variables" with "objects". In Python, variables are always mutable but not all objects are mutable. The `id` built-in gives you the address of the object, not the address of the variable. I hope this helps you understand. –  Jul 25 '19 at 12:16
  • I think here *variables are always mutable* you are assuming rebinding is mutating.. see [here](https://stackoverflow.com/questions/29967086/are-elixir-variables-really-immutable) – Yugandhar Chaudhari Jul 25 '19 at 12:26
  • @YugandharChaudhari Could you show me the Python documentation for "rebinding"? Also, I fail to see how a link to a question about another language is relevant. –  Jul 25 '19 at 12:31
  • here is an [article](https://frecar.no/mutation-rebinding-python/). A good explanation [here](https://mathieularose.com/python-variables/) .. what is your point rebinding is a new word? – Yugandhar Chaudhari Jul 25 '19 at 12:42
  • Now that I understand what you mean by "binding" the next question is what are you testing for mutability? Are you trying to test the variable for mutability? Or are you trying to test the value for mutability? –  Jul 25 '19 at 12:58
  • correct me if I am wrong I assume a variable is a name here as Tim said above. That stores where address of values is stored so may be a container for just addresses I want to test if I rebind the value if it is mutable is it holding the same address... all you people helped me to correct my question but still I think I can not visualise what variable here actually is – Yugandhar Chaudhari Jul 25 '19 at 13:09
  • 1
    A Python variable is like a C pointer: It stores the information needed access a value. In CPython, the information stored in a variable is the address of the value. But there is no way to prevent a Python variable from storing a different address. When people talk about mutability in Python, they are talking about the mutability of the value. A value of type `list` is mutable, a value of type `tuple` is not mutable. So when you appeared to be trying to test if a variable was mutable, I was completely confused. –  Jul 25 '19 at 13:22