Skip to content

Everything is an object: identity, type and value

AdvancedLesson 9 of 148 min

See how Python really stores data: every value is an object with an identity, a type and a value. Watch id() stay put or change, and learn is versus ==.

In Python, every value is an object: numbers, strings, lists, functions, even classes and modules. And every object has three things:

  • an identity, which never changes while the object exists. id(x) shows it as a number (in CPython, the version running here, it's the object's address in memory);
  • a type, which also never changes: type(x);
  • a value, which may or may not be able to change, depending on the type.

A name like x isn't any of these. It's a reference that leads to an object.

Two equal lists, or one list?

== asks "do these have the same value?". is asks "are these the same object?", which is the same as comparing their ids. Run this and compare the numbers:

mine = ["pears", "rice"]
yours = ["pears", "rice"]
ours = mine

print(mine == yours, mine is yours)  # True False
print(mine == ours, mine is ours)    # True True
print(id(mine), id(yours), id(ours))

Two of the three ids match. yours was built separately, so it's a second object that happens to hold the same items. ours = mine copied nothing at all: it made a second name for the one list that already existed.

Changing an object, or getting a new one

Watch the id when the value changes:

basket = ["pears"]
print(id(basket))
basket.append("rice")
print(id(basket))  # the same: the list itself changed

count = 10
print(id(count))
count = count + 1
print(id(count))   # different: count now names another object

A list is mutable: append changes the object in place, so its id stays. An int is immutable: there's no way to change the object 10, so count + 1 makes a new object, 11, and the name moves to it. Strings, floats, tuples, True and None are immutable too.

Types are objects too

print(type(42), type("hi"), type(print))
print(type(int))           # <class 'type'>: int is an object whose type is type
say = print                # a function is an object: give it another name
say("Hello from say")

When to use is

Use == to compare values, almost always. Use is for None: there is only ever one None object, so if result is None: is exact and fast.

Don't use is to compare numbers or strings. Whether two equal values share one object is up to Python, not you:

a = int("256")
b = int("256")
print(a is b)   # True: CPython keeps one object for each small int
c = int("1000")
d = int("1000")
print(c is d)   # False: two objects, equal values

Python even warns about it: x is 1000 gets a SyntaxWarning suggesting ==.

More in the Python docs: objects, values and types, id() and identity comparisons.

Your turn

Make twin a new list equal to original but a separate object, and alias another name for original itself. Print the ids of all three (two should match). Then append 40 through alias, print original, and see what happened to it.

Next →