Yousuf Memon
Yousuf Memon

Reputation: 4798

Reference vs Assignment in Python mutable objects

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?

Upvotes: 2

Views: 799

Answers (4)

arshajii
arshajii

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; 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".

Upvotes: 9

bruno desthuilliers
bruno desthuilliers

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

zhangxaochen
zhangxaochen

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

RyPeck
RyPeck

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

Related Questions