Classes and Objects
|
This section documents the current Python release line as published at the official Python documentation, which is the reference these pages are written and verified against. No specific patch version is pinned. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
A class is a blueprint for objects that bundle state (attributes) and behaviour (methods). Python’s class mechanics are covered in the tutorial’s Classes chapter; this page sticks to what you need to define and use one — the full special-method ("dunder") treatment is on Operator Overloading, and multiple inheritance / MRO on Advanced OOP Design.
class Basics, init, Attributes, and self
A class statement defines a new type. _init_ is the initializer, called automatically right after a
new instance is created, and is where instance attributes are usually set:
class Dog:
species = "Canis familiaris" # class attribute: shared by all instances
def __init__(self, name, age):
self.name = name # instance attribute: unique per instance
self.age = age
def describe(self): # instance method
return f"{self.name} is {self.age} year(s) old"
Every method’s first parameter is conventionally named self — it is the instance the method was called
on, passed automatically by Python. A class attribute (species above) lives on the class object and is
shared by every instance unless an instance sets its own attribute of the same name, which then shadows the
class attribute for that instance only:
rex = Dog("Rex", 3)
fido = Dog("Fido", 5)
print(rex.species, fido.species) # Canis familiaris, Canis familiaris (shared)
rex.species = "Rex's own species" # creates an *instance* attribute, doesn't touch the class one
print(rex.species, fido.species) # Rex's own species, Canis familiaris
Mutable class attributes (a list or dict) are a common trap: mutating one through an instance mutates the
shared object seen by every instance, so per-instance mutable state belongs in init instead. See
the Classes tutorial for the full attribute lookup rules.
Creating Instances; @staticmethod and @classmethod
Calling a class like a function creates an instance — Dog("Rex", 3) runs Dog.init on a freshly
created object and returns it. An instance method (the default) receives self and can read or mutate
that instance’s state:
print(rex.describe()) # Rex is 3 year(s) old
A @staticmethod takes neither self nor the class — it’s a plain function namespaced under the class,
used when the logic doesn’t need instance or class state:
class TemperatureConverter:
@staticmethod
def celsius_to_fahrenheit(c):
return c * 9 / 5 + 32
print(TemperatureConverter.celsius_to_fahrenheit(100)) # 212.0
A @classmethod takes the class itself (conventionally named cls) instead of an instance, and is the
idiomatic way to write an alternative constructor:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name, birth_year, current_year):
return cls(name, current_year - birth_year) # cls(...) == Dog(...)
rex = Dog.from_birth_year("Rex", 2021, 2024)
print(rex.name, rex.age) # Rex 3
Both decorators are documented under
staticmethod and
classmethod.
Inheritance: class Child(Parent), Overriding, and super()
A class inherits from another by naming it in parentheses; the child gets every attribute and method of the parent and can override any of them by redefining it with the same name:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound"
class Cat(Animal):
def speak(self): # overrides Animal.speak
return f"{self.name} says Meow"
generic = Animal("Something")
cat = Cat("Whiskers")
print(generic.speak()) # Something makes a sound
print(cat.speak()) # Whiskers says Meow
super() returns a proxy to the parent class, letting an override call the parent’s version instead of
fully replacing it — typically to extend init with additional attributes:
class Cat(Animal):
def __init__(self, name, indoor):
super().__init__(name) # runs Animal.__init__, sets self.name
self.indoor = indoor
def speak(self):
base = super().speak() # reuse the parent's message
return f"{base} (meow, specifically)"
whiskers = Cat("Whiskers", indoor=True)
print(whiskers.speak()) # Whiskers makes a sound (meow, specifically)
print(isinstance(whiskers, Animal)) # True
Inheritance and super() are covered in
the tutorial’s Inheritance section; single
inheritance is the common case, and combining several base classes brings in method-resolution-order
questions covered on Advanced OOP Design.
repr and str for Basic Display
Without any customization, printing an instance shows an unhelpful default like
<main.Dog object at 0x…>. Two special methods control this: _repr_ should return an unambiguous,
developer-facing representation (ideally one that could recreate the object), and _str_ returns a
human-readable string used by print() and str() — Python falls back to _repr_ when _str_ is
absent:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Dog(name={self.name!r}, age={self.age!r})"
def __str__(self):
return f"{self.name} ({self.age}y)"
rex = Dog("Rex", 3)
print(rex) # Rex (3y) -- uses __str__
print(repr(rex)) # Dog(name='Rex', age=3) -- uses __repr__
print([rex]) # [Dog(name='Rex', age=3)] -- containers always use __repr__ on their elements
This is a small slice of Python’s data model — the full catalogue of special methods (operator overloading, comparisons, container protocols, and more) lives under Basic customization in the language reference, and is covered end to end on Operator Overloading.
See Also
-
Operator Overloading — the full dunder-method treatment (operators, comparisons, container protocols).
-
Advanced OOP Design — multiple inheritance and method resolution order (MRO).