Most classes in Python should have been functions. The test is not “is this a noun” — it is whether there is invalid state a class can prevent.
self is a parameter name, not a keyword. __init__ does not create the object. And a class attribute is shared until the moment you assign through an instance.
A class without __repr__ wastes your time from the moment it exists. repr is for you, str is for the reader, and one of them has a sensible fallback.
Python has no need for getters and setters, because @property lets you add validation later without changing a single caller.
The question is only ever what the method needs — this instance, the class, or neither. Getting it wrong quietly breaks subclasses.
Inheritance gives a subclass everything, including what it should not have. The penguin problem, and what to do instead.
Every operator and built-in in Python is asking your object a question. Answer it and your class behaves like a native type.
Four ways to hold structured data in Python. The deciding question is not style — it is whether a typo should fail loudly.
Duck typing fails at the call site, long after the mistake. ABCs and Protocols both fix that, in opposite directions.
__slots__ removes the per-instance dict. It saves real memory at scale, catches typos for free, and is the wrong default.
Every operator, every built-in, every piece of syntax in Python is a question asked of your object. The data model is the list of questions.