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 == b | a is b |
|---|---|
| Same value? | Same object? |
| Calls a.eq(b) | Compares id(a) == id(b) |
| Use for numbers, strings, lists, everything | Use 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.