2

Assignment:

>>> a = ['spam']
>>> b = ['spam']
>>> a is b
False

Reference:

>>> c = ['spam']
>>> d = c
>>> c is d
True
  1. What is the difference between above both?
  2. Why assignment results False?
  3. Why reference results True?
Cœur
  • 37,241
  • 25
  • 195
  • 267
Yousuf Memon
  • 4,638
  • 12
  • 41
  • 57

4 Answers4

9

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 | &lt------ 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; the id() 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".

Community
  • 1
  • 1
arshajii
  • 127,459
  • 24
  • 238
  • 287
  • So, why the result of both is ``True`` if I try above on a immutable object like str ``spam`` instead of list ``['spam']`` – Yousuf Memon Jan 13 '14 at 14:02
  • 1
    @YousufMemon That's because [strings are interned in CPython](http://stackoverflow.com/questions/15541404/python-string-interning). – arshajii Jan 13 '14 at 14:03
  • Should I add the above comment to main question. Also can you please suggest a right title for my question. – Yousuf Memon Jan 13 '14 at 14:04
  • @YousufMemon Also try again with the string 'spam.com' and you will find a different result ;) – wim Jan 13 '14 at 14:06
  • @wim Yeah, It differed. Why was that? – Yousuf Memon Jan 13 '14 at 14:11
  • @YousufMemon See [this](http://stackoverflow.com/questions/16756699/is-operator-behaves-differently-when-comparing-strings-with-spaces?lq=1). – arshajii Jan 13 '14 at 14:15
4

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

zhangxaochen
  • 32,744
  • 15
  • 77
  • 108
1

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.)
RyPeck
  • 7,830
  • 3
  • 38
  • 58
1

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).

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118