Reputation: 4798
Assignment:
>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
Reference:
>>> c = ['spam']
>>> d = c
>>> c is d
True
False
?True
?Upvotes: 2
Views: 799
Reputation: 129507
Your first snippet creates two unique list objects, which are not the same. Hence a is b
returns false because a
and b
are pointing to distinct objects:
+------+ a ------> | list | +------+ +------+ b ------> | list | +------+
Your second snippet creates a single list object, and points both c
and d
to that objects, hence c is d
return true:
+------+ c ------> | list | <------ d +------+
Note the following, from http://docs.python.org/3/reference/datamodel.html:
Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The
is
operator compares the identity of two objects; theid()
function returns an integer representing its identity.
So is
and ==
are very different; while the former compares object identity, the latter compares object values. Indeed, ==
tests in your snippets would return true.
Given the explanation above, it may come as a surprise that that the story is slightly different with strings:
>>> a = 'str'
>>> b = 'str'
>>>
>>> a is b
True
This is due to string interning, which occurs in CPython (i.e. it's implementation specific). Therefore, if the same string literal shows up in two different places, the same string object will be used for both (with restrictions).
This is explained in greater detail in "Python string interning".
Upvotes: 9
Reputation: 77912
This has nothing to do with some (inexistant) "assignment vs reference" question.
>>> a = ['spam']
creates a list with the string 'spam' in it, and binds it to names 'a' in the current scope.
>>> b = ['spam']
creates another list with the string 'spam' in it, and binds it to names 'b' in the current scope.
You create two lists, you have two lists. Plain simple.
>>> c = ['spam']
creates yet another list with the string 'spam' in it, and binds it to names 'c' in the current scope.
>>> d = c
binds name 'd' to whatever 'c' is bound to at that time in the current scope.
Here you create one list and bind 2 names to it. Both name points to the same object.
The point is: Python's "variables" are not named memory adresses, just names pointing to objects. At a given time, one object can be bound to (pointed to by) any number of names (and even by no name at all).
Upvotes: 1
Reputation: 34017
when compare with is
, like a is b
, it's the same as id(a) == id(b)
, the code xx=['spam']
creates a new list each time and assigns it to xx
, it's id
changes each time, so a is b
gives False
Upvotes: 4
Reputation: 8147
Let me just add a few function calls to what you were originally doing. I think you will pick it up.
>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False
>>> id(a)
4552359808
>>> id(b)
4552446176
>>> a == b
True
>>> c = ['spam']
>>> d = c
>>> id(c)
4552513296
>>> id(d)
4552513296
>>> c is d
True
>>> c == d
True
>>> print id.__doc__
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
Upvotes: 1