Classes and objects — the basics
The starting point for everything else in this domain — what a class actually is, what an object is, and the two special methods every class you write will have.
3 min read
An object bundles data and behavior together
name = "Ada" # just a string
age = 25 # just a numbervs.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hi, I'm {self.name}")
ada = Person("Ada", 25)
ada.greet() # "Hi, I'm Ada"A plain variable holds one piece of data. An object bundles related data (name, age) together with the functions that operate on that data (greet) into one single thing. A class is the blueprint that describes what data and behavior every object built from it will have; an instance (ada) is one actual object built from that blueprint. Person describes the shape "a person has a name, an age, and can greet"; ada is one specific person matching that shape. You can create as many independent instances from the same class as you want, each with its own separate data.
__init__: what runs when you create an object
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
ada = Person("Ada", 25)
grace = Person("Grace", 36)__init__ (short for "initialize") runs automatically every time a new instance is created — Person("Ada", 25) calls it, passing "Ada" and 25 in as name and age. Its job is almost always the same shape: take in some starting values, and store them on the object via self.attribute = value so they can be used later by other methods. ada and grace are two completely independent objects — changing ada.name has no effect on grace.name whatsoever, because each instance has its own separate copy of the data __init__ set up for it.
self: how a method refers to "this particular object"
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def have_birthday(self):
self.age += 1Every method defined inside a class takes self as its first parameter — it's how the method refers to the specific instance it's being called on. ada.have_birthday() runs have_birthday with self automatically bound to ada, so self.age += 1 increments ada.age specifically, not some other person's age. You don't pass self explicitly when calling a method (ada.have_birthday(), not ada.have_birthday(ada)) — Python fills it in automatically because you called the method on ada.
Attributes and methods: the two things a class defines
class Person:
species = "Homo sapiens" # class attribute — shared by every instance
def __init__(self, name, age):
self.name = name # instance attribute — unique per instance
self.age = age
def greet(self): # method — behavior every instance can do
print(f"Hi, I'm {self.name}")An attribute is a piece of data stored on an object (self.name); a method is a function defined inside the class that operates on that data (greet). There's also a distinction worth knowing early: an attribute set inside __init__ via self.x = ... is an instance attribute — every object gets its own separate copy. An attribute defined directly in the class body (species above) is a class attribute — shared by every instance of the class unless a specific instance overrides it.
__str__: controlling how an object prints
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} ({self.age})"
ada = Person("Ada", 25)
print(ada) # without __str__: <__main__.Person object at 0x...>
# with __str__: Ada (25)Without a __str__ method, printing an object shows Python's unhelpful default representation — the class name and a memory address, not useful information. Defining __str__ to return a readable string is one of the first "special methods" (also called dunder methods, for the double underscores) worth learning, since almost every class benefits from being printable in a way a human can actually read. There are many more special methods (covering equality, comparison, arithmetic, and more) that let a custom class integrate with Python's built-in behaviors — worth exploring once classes themselves feel comfortable.
Further reading
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What's the actual difference between a class and an instance?
2. What does __init__ actually do?
3. Why does every method inside a class take self as its first parameter?
4. What's the difference between an instance attribute and a class attribute?