Python Class Methods & Class Attributes
Instance vs Class: The Key Distinction
| Instance | Class | |
|---|---|---|
| Associated with | A specific object | The class itself |
| Keyword | self |
cls |
| Needs an instance to access? | Yes | No |
| Shared across all instances? | No | Yes |
Class Attributes
A class attribute is defined directly inside the class body — not inside any method and not prefixed with self.
class Car:
number_of_cars = 0 # class attribute
wheels = 4 # class attribute
def __init__(self, make, model):
self.make = make # instance attribute
self.model = model # instance attribute
Accessing Class Attributes
# Via the class (preferred)
print(Car.number_of_cars) # 0
# Via an instance (works, but not preferred)
c1 = Car("Ford", "Edge")
print(c1.number_of_cars) # 0
Modifying a Class Attribute
Car.number_of_cars += 3
print(Car.number_of_cars) # 3
⚠️ If you assign via an instance (
c1.number_of_cars = 1), Python creates a new instance attribute on that object — it does NOT modify the class attribute.
Tracking Instance Count with a Class Attribute
class Car:
number_of_cars = 0
def __init__(self, make, model):
self.make = make
self.model = model
Car.number_of_cars += 1 # update class attribute on every new instance
c1 = Car("Ford", "Edge")
c2 = Car("Mazda", "3")
print(Car.number_of_cars) # 2
When to Use a Class Attribute
Use a class attribute when the value is: - The same for every instance (e.g. all cars have 4 wheels) - Shared and updated across all instances (e.g. a running count)
Use an instance attribute for anything specific to one object (e.g. make, model).
Class Methods
A class method acts on the class itself, not on any instance. It is defined with the @classmethod decorator and takes cls (the class) as its first parameter instead of self.
class Car:
number_of_cars = 0
@classmethod
def update_number_of_cars(cls, cars):
cls.number_of_cars = cars
Calling a Class Method
# Via the class (preferred)
Car.update_number_of_cars(10)
# Via an instance (works, but cls still refers to Car — not the instance)
c1 = Car("Ford", "Edge")
c1.update_number_of_cars(10)
Rules for Class Methods
- Always use
@classmethoddecorator above the definition - First parameter is always
cls(stands for the class — likeselfbut for the class) clsis a hidden parameter — passed automatically, just likeself- Can only access class attributes and other class methods
- ❌ Cannot access instance attributes (
self.make,self.model, etc.) — there's no instance context
Practical Example — Circle Class
A common use case: grouping related utility methods together under one class, with a shared class attribute.
class Circle:
pi = 3.14 # class attribute — change once, updates all methods
@classmethod
def area(cls, radius):
return cls.pi * radius ** 2
@classmethod
def perimeter(cls, radius):
return 2 * cls.pi * radius
@classmethod
def get_area_and_perimeter(cls, radius):
return cls.area(radius), cls.perimeter(radius)
Usage
print(Circle.area(2)) # 12.56
print(Circle.perimeter(4)) # 25.12
print(Circle.get_area_and_perimeter(4)) # (50.24, 25.12)
No instances needed — everything works directly on the class.
Why Group Methods in a Class Like This?
- All related logic is in one place
- One change to
piupdates every method automatically - Class methods can call other class methods cleanly via
cls
Key Takeaways & Recap
| Concept | Summary |
|---|---|
| Class attribute | Defined in the class body, no self; shared by all instances |
| Instance attribute | Defined with self; unique to each object |
@classmethod |
Decorator that marks a method as a class method |
cls |
Refers to the class itself (not an instance) |
| Access rule | Class methods can only use class-level attributes and methods |
| Preferred access | Use ClassName.attribute / ClassName.method() for class-level things |