Reading — step 1 of 8
Learn
Up to this point, you've been using Python's built-in types — strings, lists, dicts. But what happens when you need to represent something more complex? A bank account has a balance AND can deposit AND can withdraw. A web request has a URL AND headers AND can be sent. A game character has stats AND can attack AND can level up.
Classes solve this. A class is a blueprint that bundles data (attributes) and behavior (methods) together. An object (or instance) is a specific thing built from that blueprint. Two BankAccount objects can each have their own balance, but they share the same deposit method.
Defining a class
Four pieces:
class ClassName:— convention: PascalCase for class names.__init__— the initializer (often called the constructor). Runs automatically when you create an instance.self— the specific instance the method is being called on. ALWAYS the first parameter of any instance method.- Attributes —
self.owner,self.balance. Set them viaself.attr = value.
Creating instances
Note: you DON'T pass self — Python passes it for you when you call alice.deposit(50).
What is self, really?
When you call alice.deposit(50), Python translates this to BankAccount.deposit(alice, 50). self is just the instance the method was called on. That's it.
Two instances of the same class have separate attribute storage but share the same method definitions. That's why alice.deposit and bob.deposit are the same code — but operating on different self.
Class attributes vs instance attributes
Class attributes are like "constants for the class." Use sparingly — most data should be on self.
Methods that don't take self — @classmethod, @staticmethod
@classmethod— receives the class itself asclsinstead of an instance. Often used for alternative constructors.@staticmethod— receives nothing automatic. A regular function that just lives inside the class for organization.
Privacy convention — leading underscore
Python has no truly private attributes, but a leading underscore is a strong convention meaning "don't touch this from outside":
Double-underscore (e.g. __balance) triggers name mangling — Python renames it to _ClassName__balance. Rarely needed.
__repr__ — make print() useful
Without __repr__, print(alice) shows something like <__main__.BankAccount object at 0x7f...>. Adding __repr__ makes debugging far easier. (More dunder methods in lesson 3.)
Common mistakes
- Forgetting
selfin method definitions:def deposit(amount):is missingself. Python won't complain at definition but you'll get a TypeError at call time. - Passing self when calling:
alice.deposit(alice, 50)is a bug — Python passes self for you. - Defining attributes outside
__init__is allowed but sloppy:alice.balance = 100after construction works but you've sidestepped your own constructor. - Using class attributes for mutable state: a class attribute that's a list is SHARED between instances!
class Foo: items = []thenFoo().items.append(1)mutates the class-level list. Useself.items = []in__init__.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…