You know OOP from Java — but Python's object model is more transparent and a little more
surprising. Attributes live in plain dictionaries, the class is itself an object, and lookup follows one
simple rule: instance first, then class. Get that rule and class-vs-instance variables,
self, and @property all click.
Every instance carries its own little dictionary of attributes (its __dict__). The class has
a separate namespace holding things shared by all instances — methods, and any class variables.
When you read obj.x, Python looks in the instance first; only if it's not there does it
fall back to the class. That single rule explains a lot.
An instance variable (set with self.x = …, usually in __init__) is unique
to each object. A class variable (declared in the class body) is shared by all of them — until an
instance assigns to that name, which creates an instance variable that shadows the class one for
that object only. Try it: read attributes (watch the lookup path) and assign them (watch where the value
lands).
Class Account has a shared class var
bank; each instance gets its own owner & balance.
What about the functions in the class body? They differ only by what automatic first argument they get:
self — Python passes the object automatically, so
a1.deposit(10) really calls Account.deposit(a1, 10). self isn't a
keyword; it's just the conventional name for that first parameter.cls (the class) instead — perfect for alternative constructors
like Account.from_dict(...).@property: a method that looks like an attributeJava reflexively wraps fields in getBalance()/setBalance(). Python says: just
expose the attribute — and if you later need logic on access, add it without changing the callers,
using @property:
It runs a method but is read like a field — no (). That keeps your public surface clean while
still letting you compute, validate, or cache behind it.
self.x makes a per-object instance var; a name in the class body is a shared class
var (assigning it on an instance shadows, never mutates the shared one). Methods differ by their
auto first arg: self (instance), cls (@classmethod), nothing (@staticmethod).
@property exposes a method as a parenthesis-free attribute.See instances and their __dict__s as real boxes in
Python Tutor. Next:
inheritance & the MRO →