Everything is an object

Part of the free LogicWiz Python course, Module 13: Python under the hood. The examples and practice run in the app.

Aarav wrote if price is 100: in Canteen Counter and it worked. Then a ₹1000 party order came in, the same check said False, and the order was never billed. Same code, different number. Why?

You'll learn to

  • Explain that names are labels pointing to objects, each with an identity, a type and a value
  • Choose correctly between `is` and `==`
  • Tell mutable from immutable objects and predict what changes
  • Explain "pass by object reference" with a function that changes a list

Learn

Every value is an object

In Python every value is an object: 5, "chai", [1, 2], even a function. Each object has three things:

  • an identity: where it lives in memory; id(x) gives a number for it
  • a type: type(x), which decides what you can do with it
  • a value: what it holds

A name like price is not a box holding the value. It is a label tied to an object. price = 5 ties the label price to the object 5. Two labels can be tied to the same object.

Two names, one list

a = [10, 20]
b = a
b.append(30)
print(a)
print(id(a) == id(b))
c = [10, 20, 30]
print(a == c, a is c)

b = a copies nothing. It ties a second label to the same list, so a sees the change. c is a different list that happens to hold equal values.

`==` vs `is`

a == ba is b
Same value?Same object?
Calls a.eq(b)Compares id(a) == id(b)
Use for numbers, strings, lists, everythingUse for None (and sentinels): if x is None:
[1] == [1] is True[1] is [1] is False

Why `price is 100` "worked"

x = int("100")
y = int("100")
print(x == y, x is y)
p = int("1000")
q = int("1000")
print(p == q, p is q)

CPython keeps one ready-made object for each small integer from -5 to 256, so every 100 is the same object. 1000 is built fresh each time. This is a speed trick of CPython, not a rule of Python, so never use is to compare numbers or strings.

Mutable vs immutable

Immutable objects can never change after they are made: int, float, bool, str, tuple, frozenset. Mutable objects can change in place: list, dict, set, and most objects of your own classes.

So what does n += 1 do to an int? It cannot change the 5 object. It builds a new object 6 and moves the label n to it. For a list, nums += [6] changes the same list in place.

Watch the identity

n = 5
old = id(n)
n += 1
print(id(n) == old)
nums = [5]
old = id(nums)
nums += [6]
print(id(nums) == old)

Pass by object reference

Is Python "pass by value" or "pass by reference"? Neither. When you call f(order), the parameter inside f becomes one more label on the same object. This is called pass by object reference (or "pass by assignment").

  • If the function changes the object (bill.append(10)), the caller sees it.
  • If the function rebinds its label (bill = []), only its own label moves. The caller is untouched.

Change vs rebind inside a function

def add_tip(bill):
    bill.append(10)

def reset(bill):
    bill = []

order = [50, 20]
add_tip(order)
reset(order)
print(order)

Never write if total is 1000: or if name is "chai":. It may work for some values and fail for others, and Python 3.8+ even prints a SyntaxWarning for is with a literal. Use == for values. Keep is for None, True/False checks against a sentinel, and "is this the very same object?" questions.

In one line

Names are labels on objects; == compares values, is compares identity (use it only for None); functions get a new label on the same object.

Interview corner

What is the difference between `is` and `==`?

== checks whether two objects have equal values (it calls __eq__). is checks whether two names point to the same object (same id). [1, 2] == [1, 2] is True but [1, 2] is [1, 2] is False. Use is only for singletons like None: if x is None:.

Is Python pass by value or pass by reference?

Neither: it is pass by object reference. The parameter becomes a new name for the caller's object. If the function mutates that object (a list .append), the caller sees the change; if it rebinds the parameter (x = []), the caller does not.

Why does `a = 256; b = 256; a is b` give `True` but it can be `False` for 1000?

CPython pre-creates and reuses integer objects from -5 to 256, so every 256 is the same object. Larger integers are usually created fresh, so two equal values can be different objects. It is an implementation detail; compare numbers with ==.

What are mutable and immutable types? Why are strings immutable?

Mutable objects (list, dict, set) can change in place; immutable ones (int, str, tuple, frozenset) cannot, and "changing" them makes a new object. Strings are immutable so they can be hashed (used as dict keys), shared safely between names, and cached or interned.