This question already has answers here:
identifying objects, why does the returned value from id(...) change?
(7 answers)
Python integer caching
(2 answers)
Closed 6 years ago.
In Python I created integer and list objects as follows:
a = 10
b = 10
x = []
y = []
Then I get the following results while comparing the id of a and b, and the id of x and y
id(a)==id(b) returns True
id(x)==id(y) returns False
Somewhere I read that assignment in Python never copies data. My question is why x and y do not have the same id?
You must know that python integers ar cached and inmutable, that means that both a and b are labeling the same 10. Lists are objects and they are allocated separetly, thats why their ids are diferent from the beggining
Lists are mutable, if the same object was used, when you add an item to one of the list, you'd see the change on the other one as well.
Identity of integers is implementation dependent, and it is usually valid only for small numbers; good reading here.
By the way, == is the equality operator. A shortest (and cleaner) way for id(a)==id(b) is to use the identity operator is. In your case: a is b.
x = [] is a shorthand for instantiating a new list, which means a new object with a new object ID. Even though x and y are assigned as empty lists, they are simply references to memory locations allocated for the respective lists. If id(x) == id(y) then x and y would share the same object ID, which would effectively mean they share a memory location, or are references to the same object (so any changes made to one would apply to the other).
On the other hand, id(a) == id(b) because they are both integers, which are primitive data types.
Related
I read the Python 2 docs and noticed the id() function:
Return the “identity” of an object. This is an integer (or long 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.
So, I experimented by using id() with a list:
>>> list = [1,2,3]
>>> id(list[0])
31186196
>>> id(list[1])
31907092 // increased by 896
>>> id(list[2])
31907080 // decreased by 12
What is the integer returned from the function? Is it synonymous to memory addresses in C? If so, why doesn't the integer correspond to the size of the data type?
When is id() used in practice?
Your post asks several questions:
What is the number returned from the function?
It is "an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime." (Python Standard Library - Built-in Functions) A unique number. Nothing more, and nothing less. Think of it as a social-security number or employee id number for Python objects.
Is it the same with memory addresses in C?
Conceptually, yes, in that they are both guaranteed to be unique in their universe during their lifetime. And in one particular implementation of Python, it actually is the memory address of the corresponding C object.
If yes, why doesn't the number increase instantly by the size of the data type (I assume that it would be int)?
Because a list is not an array, and a list element is a reference, not an object.
When do we really use id( ) function?
Hardly ever. You can test if two references are the same by comparing their ids, but the is operator has always been the recommended way of doing that. id( ) is only really useful in debugging situations.
That's the identity of the location of the object in memory...
This example might help you understand the concept a little more.
foo = 1
bar = foo
baz = bar
fii = 1
print id(foo)
print id(bar)
print id(baz)
print id(fii)
> 1532352
> 1532352
> 1532352
> 1532352
These all point to the same location in memory, which is why their values are the same. In the example, 1 is only stored once, and anything else pointing to 1 will reference that memory location.
Rob's answer (most voted above) is correct. I would like to add that in some situations using IDs is useful as it allows for comparison of objects and finding which objects refer to your objects.
The later usually helps you for example to debug strange bugs where mutable objects are passed as parameter to say classes and are assigned to local vars in a class. Mutating those objects will mutate vars in a class. This manifests itself in strange behavior where multiple things change at the same time.
Recently I had this problem with a Python/Tkinter app where editing text in one text entry field changed the text in another as I typed :)
Here is an example on how you might use function id() to trace where those references are. By all means this is not a solution covering all possible cases, but you get the idea. Again IDs are used in the background and user does not see them:
class democlass:
classvar = 24
def __init__(self, var):
self.instancevar1 = var
self.instancevar2 = 42
def whoreferencesmylocalvars(self, fromwhere):
return {__l__: {__g__
for __g__ in fromwhere
if not callable(__g__) and id(eval(__g__)) == id(getattr(self,__l__))
}
for __l__ in dir(self)
if not callable(getattr(self, __l__)) and __l__[-1] != '_'
}
def whoreferencesthisclassinstance(self, fromwhere):
return {__g__
for __g__ in fromwhere
if not callable(__g__) and id(eval(__g__)) == id(self)
}
a = [1,2,3,4]
b = a
c = b
democlassinstance = democlass(a)
d = democlassinstance
e = d
f = democlassinstance.classvar
g = democlassinstance.instancevar2
print( 'My class instance is of', type(democlassinstance), 'type.')
print( 'My instance vars are referenced by:', democlassinstance.whoreferencesmylocalvars(globals()) )
print( 'My class instance is referenced by:', democlassinstance.whoreferencesthisclassinstance(globals()) )
OUTPUT:
My class instance is of <class '__main__.democlass'> type.
My instance vars are referenced by: {'instancevar2': {'g'}, 'classvar': {'f'}, 'instancevar1': {'a', 'c', 'b'}}
My class instance is referenced by: {'e', 'd', 'democlassinstance'}
Underscores in variable names are used to prevent name colisions. Functions use "fromwhere" argument so that you can let them know where to start searching for references. This argument is filled by a function that lists all names in a given namespace. Globals() is one such function.
id() does return the address of the object being referenced (in CPython), but your confusion comes from the fact that python lists are very different from C arrays. In a python list, every element is a reference. So what you are doing is much more similar to this C code:
int *arr[3];
arr[0] = malloc(sizeof(int));
*arr[0] = 1;
arr[1] = malloc(sizeof(int));
*arr[1] = 2;
arr[2] = malloc(sizeof(int));
*arr[2] = 3;
printf("%p %p %p", arr[0], arr[1], arr[2]);
In other words, you are printing the address from the reference and not an address relative to where your list is stored.
In my case, I have found the id() function handy for creating opaque handles to return to C code when calling python from C. Doing that, you can easily use a dictionary to look up the object from its handle and it's guaranteed to be unique.
I am starting out with python and I use id when I use the interactive shell to see whether my variables are assigned to the same thing or if they just look the same.
Every value is an id, which is a unique number related to where it is stored in the memory of the computer.
If you're using python 3.4.1 then you get a different answer to your question.
list = [1,2,3]
id(list[0])
id(list[1])
id(list[2])
returns:
1705950792
1705950808 # increased by 16
1705950824 # increased by 16
The integers -5 to 256 have a constant id, and on finding it multiple times its id does not change, unlike all other numbers before or after it that have different id's every time you find it.
The numbers from -5 to 256 have id's in increasing order and differ by 16.
The number returned by id() function is a unique id given to each item stored in memory and it is analogy wise the same as the memory location in C.
The is operator uses it to check whether two objects are identical (as opposed to equal). The actual value that is returned from id() is pretty much never used for anything because it doesn't really have a meaning, and it's platform-dependent.
The answer is pretty much never. IDs are mainly used internally to Python.
The average Python programmer will probably never need to use id() in their code.
It is the address of the object in memory, exactly as the doc says. However, it has metadata attached to it, properties of the object and location in the memory is needed to store the metadata. So, when you create your variable called list, you also create metadata for the list and its elements.
So, unless you an absolute guru in the language you can't determine the id of the next element of your list based on the previous element, because you don't know what the language allocates along with the elements.
I have an idea to use value of id() in logging.
It's cheap to get and it's quite short.
In my case I use tornado and id() would like to have an anchor to group messages scattered and mixed over file by web socket.
I'm a little bit late and i will talk about Python3. To understand what id() is and how it (and Python) works, consider next example:
>>> x=1000
>>> y=1000
>>> id(x)==id(y)
False
>>> id(x)
4312240944
>>> id(y)
4312240912
>>> id(1000)
4312241104
>>> x=1000
>>> id(x)
4312241104
>>> y=1000
>>> id(y)
4312241200
You need to think about everything on the right side as objects. Every time you make assignment - you create new object and that means new id. In the middle you can see a "wild" object which is created only for function - id(1000). So, it's lifetime is only for that line of code. If you check the next line - you see that when we create new variable x, it has the same id as that wild object. Pretty much it works like memory address.
As of in python 3 id is assigned to a value not a variable. This means that if you create two functions as below, all the three id's are the same.
>>> def xyz():
... q=123
... print(id(q))
...
>>> def iop():
... w=123
... print(id(w))
>>> xyz()
1650376736
>>> iop()
1650376736
>>> id(123)
1650376736
Be carefull (concerning the answer just below)...That's only true because 123 is between -5 and 256...
In [111]: q = 257
In [112]: id(q)
Out[112]: 140020248465168
In [113]: w = 257
In [114]: id(w)
Out[114]: 140020274622544
In [115]: id(257)
Out[115]: 140020274622768
This question already has answers here:
Understanding the "is" operator [duplicate]
(11 answers)
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
Closed 1 year ago.
Why is this:
x = str(input("Enter a string: ")) #input "cat"
y = str(input("Enter another string: ")) #input "cat"
print(x is y) #Outputs False
Not the same as this:
x = "cat"
y = "cat"
print(x is y) #Outputs True
From this Real Python article:
The == operator compares the value or equality of two objects, whereas the Python is operator checks whether two variables point to the same object in memory. In the vast majority of cases, this means you should use the equality operators == and !=, except when you’re comparing to None.
>>> x = None
>>> y = None
>>> id(x); id(y)
4389651888
4389651888
>>> x is y
True
== calls the __eq__ method of an object, is checks whether the id() of two objects is equal (memory address).
The rest of the article I linked is really informative; it talks about how Python will give the same id to small integers by default, and that you can use the sys.intern() method to ensure string variables point to the same object in memory as well.
The is operator in python is used to check if two objects point to the same memory location.
In the second case, when python runs, for optimization purposes both x and y point to the same memory location. However, in the first case, x and y are not defined until the user inputs a value during run time. So, they're both allocated memory in different locations.
The main ideas of immutability are kept the same throughout the scope of OOP and functional programming or do, for example, Java and Python have their own versions of immutability. More specifically do the following hold in all languages?
Mutable Objects: Set, Dict, List
Immutable Objects: Bool, Int, Float, String, Tuple
In python two immutable objects with the same value also have the same id, two references one value.
In python again two mutable objects with the same value don't share the same id, two references two values.
Does this idea of two references binding together in mutable objects hold in all languages? And the reverse as well, that is, bindings cannot be changed, meaning that references can only change the value they are pointing to.
i = {1,2,3} # Set, a mutable object
j = {1,2,3}
i is j
False
i = j
j.remove(3)
i is j
True
I'm asking because for example in scripting languages objects are passed by references (in other languages passed by value or in C where we have both) so doesn't this change the whole notion of immutability?
If you have any object, even literal ones, it needs to use some space in memory.
This memory needs to be mutated by the language runtime and it is the same if it's immutable or not. Thus mutable objects mutate memory when object gets created.
Thus an immutable object is one that either is ensured not to be changed at compile time or protected by the runtime when the program runs.
In python two immutable objects with the same value also have the same
id, two references one value.
I don't think this is guaranteed at all. Eg.
x = (1,2,3)
y = (1,2,3)
x is y
// => False
When I run it in my repl. If it's anything like Common Lisp and Java it might happen that implementations are free to reuse memory locations of the same literals and thus any boolean result would be acceptable.
What is my understanding of the difference between mutable vs immutable in python is the that the first can be changed by indexing. For example, the following x list can be changed by indexing!
x = [1,2,3]
x[0] = 10
y = (1,2,3)
y[0] = 10 # this will raise an error. tuple is not mutable.
y = x
id(y) == id(x) #gives true. since y is a reference to x
y[0] = 10
print(y)
[10, 2, 3]
print(x)
[10, 2, 3] # x is changed as well! y and x are same same.
every time you create lists or sets or tuples with unique names even though they contain the same dataset, still they are not the same list mapped into the memory. each has its unique id.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python “is” operator behaves unexpectedly with integers
I'm learning Python, and am curious as to why:
x = 500
x is 500
returns False, but:
y = 100
y is 100
returns True?
Python reuses small integers. That is, all 1s (for example) are the same 1 object. The range is -5 to 255, if I remember correctly, though this is a CPython implementation detail that should not be relied upon. I am pretty sure Jython and IronPython, for example, handle this differently.
The reason this works out fine is that ints are immutable. That is, you can't change a 4 to a 5 in-place. if a has a value of 4, a = 5 is actually pointing a to a different object, not changing the value a contains. Python doesn't share any mutable types (such as lists) where unexpectedly having multiple references to the same object might cause problems.
You should use == for comparing most things. is is for checking to see whether two references point to the same object; it is roughly equivalent to id(x) == id(y).
is tests for identity - x is y asks if they are the same object, not if they are simply 'equivalent'. So you also have, eg:
>>> x = []
>>> y = []
>>> z = x
>>> x is y
False
>>> x is z
True
For equivalence, you want to test equality:
>>> x = 500
>>> x == 500
True
Python (or, at least, cpython - the major implementation) does some optimisations so that certain immutable objects only exist once throughout the lifetime of the interpreter. So, every 5 throughout your program will be the same integer object. The same thing happens with string literals, for example.
"is" compare objects IDs and "==" will compare object values. So, if you need to compare values, go with "==" and if you whant to compare objects, go with "is".
As in Python everything is an object, is compares objects IDs, it's faster, but some times unpredictable. You need to be very sure of what you are doing to use "is" for simple comparsion.
About the situation above, I found here: http://docs.python.org/c-api/int.html the following remark:
The current implementation keeps an array of integer objects for all
integers between -5 and 256, when you create an int in that range you
actually just get back a reference to the existing object. So it
should be possible to change the value of 1. I suspect the behaviour
of Python in this case is undefined. :-)
So, you can do the following test and see this behaviour:
>>> a = 256
>>> id(a)
19707932
>>> id(256)
19707932
>>> a = 257
>>> id(a)
26286076
>>> id(257)
26286064
So, for integers above 256, "is" will not work. Be careful using "is" for comparsion.
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Types for which “is” keyword may be equivalent to equality operator in Python
Python “is” operator behaves unexpectedly with integers
Hi.
I have a question which perhaps might enlighten me on more than what I am asking.
Consider this:
>>> x = 'Hello'
>>> y = 'Hello'
>>> x == y
True
>>> x is y
True
I have always used the comparison operator. Also I read that is compares the memory address and hence in this case, returns True
So my question is, is this another way to compare variables in Python? If yes, then why is this not used?
Also I noticed that in C++, if the variables have the same value, their memory addresses are different.
{ int x = 40; int y = 40; cout << &x, &y; }
0xbfe89638, 0xbfe89634
What is the reason for Python having the same memory addresses?
This is an implementation detail and absolutely not to be relied upon. is compares identities, not values. Short strings are interned, so they map to the same memory address, but this doesn't mean you should compare them with is. Stick to ==.
There are two ways to check for equality in Python: == and is. == will check the value, while is will check the identity. In almost every case, if is is true, then == must be true.
Sometimes, Python (specifically, CPython) will optimize values together so that they have the same identity. This is especially true for short strings. Python realizes that 'Hello' is the same as 'Hello' and since strings are immutable, they become the same through string interning / string pooling.
See a related question: Python: Why does ("hello" is "hello") evaluate as True?
This is because of a Python feature called String interning which is a method of storing only one copy of each distinct string value.
In Python both strings and integers are immutable therefore you can cache them. Integers in the range of ´-5´ to ´256´ and small strings(don't know the exact size atm) get cached, therefore they are the same object. x and y are only names that refer to these objects.
Also == compares for equals values, while is compares for object identity. None True and False are global objects, for example you can rebind False to True.
The following shows that not every thing is being cached:
x = 'Test' * 2000
y = 'Test' * 2000
>>> x == y
True
>>> x is y
False
>>> x = 10000000000000
>>> y = 10000000000000
>>> x == y
True
>>> x is y
False
In Python, variables are just names that point to some object (and they can point to the same object). In C++, variables also define the actual memory that is reserved for them; this is why they have distinct memory addresses.
About Python string interning and differences between the two comparison operators, see carl's response.