Question

Python Static Variables and Methods: Class Variables, @classmethod, and @staticmethod

pythonclassstaticclass-variables

Question

How can I create class-level variables and methods in Python?

I want to understand how to define variables that belong to the class itself rather than to each individual object, and how to create methods that can be called on the class without requiring an instance. In other words, how do class variables, @classmethod, and @staticmethod work in Python?

Short Answer

By the end of this page, you will understand how Python stores data on a class, how class variables differ from instance variables, and how to define methods that work at the class level using @classmethod and utility-style methods using @staticmethod. You will also see when to use each one and the mistakes beginners commonly make.

Concept

In Python, the phrase static variable is usually expressed as a class variable. A class variable is defined inside the class body and is shared by all instances of that class unless an instance overrides it.

A Python class can have three common kinds of members:

  • Instance variables: belong to one object
  • Class variables: belong to the class itself
  • Methods: functions defined inside the class

And methods themselves can be of three main types:

  • Instance methods: take self and work with one object
  • Class methods: take cls and work with the class
  • Static methods: take neither self nor cls automatically

Why this matters

This matters because real programs often need:

  • shared configuration across all objects
  • counters that track how many objects were created
  • factory methods that construct objects in a standard way
  • utility functions that logically belong inside a class

Class variables

A class variable is defined directly in the class:

class User:
    role = "member"

Here, role belongs to User, not to any one object.

All instances can read it:

u1 = User()
u2 = User()

print(u1.role)  # member
print(u2.role)  # member
print(User.role)  # member

Class methods

A class method uses the @classmethod decorator. Its first parameter is usually named cls, which refers to the class itself:

class User:
    count = 0

    @classmethod
    def show_count(cls):
        return cls.count

This is useful when a method needs to read or modify class-level data.

Static methods

A static method uses @staticmethod. It does not receive self or cls automatically:

class MathTools:
    @staticmethod
    def add(a, b):
        return a + b

This is useful when the function belongs conceptually to the class, but does not need instance or class data.

Important Python idea

Python does not use a separate static keyword like Java or C#. Instead:

  • use a class variable for shared class-level data
  • use @classmethod for methods that work with the class
  • use @staticmethod for helper functions grouped inside the class

Mental Model

Think of a class as a building blueprint.

  • An instance variable is furniture inside one specific apartment.
  • A class variable is a sign posted on the building entrance that everyone in the building can see.
  • An instance method is something one resident does inside their own apartment.
  • A class method is something the building manager does for the whole building.
  • A static method is like a rule sheet stored in the lobby: it belongs there, but it does not depend on any specific resident or even the manager.

So if data or behavior applies to the whole class, put it on the class. If it applies to one object, put it on the instance.

Take Quiz

Syntax and Examples

Core syntax

Class variable

class Dog:
    species = "Canis familiaris"

Instance variable

class Dog:
    def __init__(self, name):
        self.name = name

Class method

class Dog:
    count = 0

    @classmethod
    def get_count(cls):
        return cls.count

Static method

class Dog:
    @staticmethod
    def is_valid_name(name):
        return len(name) > 0

Example: class variable and instance variable together

class Employee:
    company = "Acme Inc."

    def __init__(self, name):
        self.name = name

emp1 = Employee("Alice")
emp2 = Employee("Bob")

print(emp1.name)      # Alice
print(emp2.name)      # Bob
print(emp1.company)   # Acme Inc.
print(emp2.company)   # Acme Inc.
print(Employee.company)  # Acme Inc.

Explanation

  • name is different for each employee, so it is an instance variable.
  • company is shared by all employees, so it is a class variable.

Example: counting created objects with a class method

class Employee:
    count = 0

    def __init__(self, name):
        self.name = name
        Employee.count += 1

    @classmethod
    def get_count(cls):
        return cls.count

emp1 = Employee("Alice")
emp2 = Employee("Bob")

print(Employee.get_count())  # 2
print(emp1.get_count())      # 2

Explanation

  • count belongs to the class.
  • Every time an Employee is created, the counter increases.
  • get_count() reads class-level data using cls.

Example: static method utility

class Temperature:
    @staticmethod
    def celsius_to_fahrenheit(c):
        return (c * 9 / 5) + 32

print(Temperature.celsius_to_fahrenheit(25))  # 77.0

Explanation

This method is related to Temperature, but it does not need any object state or class state.

Step by Step Execution

Consider this example:

class Product:
    tax_rate = 0.1

    def __init__(self, name, price):
        self.name = name
        self.price = price

    def total_price(self):
        return self.price + (self.price * Product.tax_rate)

Now run:

p = Product("Book", 20)
print(p.total_price())

Step by step

1. Python reads the class definition

class Product:

Python creates the Product class object.

2. Python stores the class variable

tax_rate = 0.1

This value is attached to the class itself.

3. Python stores the methods

def __init__(self, name, price):

and

def total_price(self):

These functions become methods of the class.

4. An instance is created

p = Product("Book", 20)

Python creates a new object and calls __init__ with:

  • self = the new object
  • name = "Book"
  • price = 20

5. Instance variables are assigned

self.name = name
self.price = price

Now the object p has:

  • p.name == "Book"
  • p.price == 20

6. The method is called

p.total_price()

Python passes p as self.

7. The method uses instance and class data

return self.price + (self.price * Product.tax_rate)
  • self.price comes from the object
  • Product.tax_rate comes from the class

So the result is:

20 + (20 * 0.1) = 22.0

8. The final output is printed

22.0

This example shows that instance methods can access both instance data and class data.

Real World Use Cases

Shared settings

class AppConfig:
    debug = True
    version = "1.0"

Useful for values shared across the application.

Object counters

class Session:
    active_sessions = 0

    def __init__(self):
        Session.active_sessions += 1

Useful for tracking how many objects have been created.

Factory methods

class User:
    def __init__(self, username, active=True):
        self.username = username
        self.active = active

    @classmethod
    def guest(cls):
        return cls("guest", active=False)

Useful when you want alternate ways to create objects.

Validation helpers

class Email:
    @staticmethod
    def is_valid(address):
        return "@" in address

Useful when a helper function belongs with a class conceptually.

Data parsing

class Order:
    def __init__(self, order_id, total):
        self.order_id = order_id
        self.total = total

    @classmethod
    def from_dict(cls, data):
        return cls(data["order_id"], data["total"])

Useful when building objects from JSON, dictionaries, or API responses.

Take Quiz

Real Codebase Usage

In real projects, developers commonly use these patterns:

Class variables for shared constants

class HTTPStatus:
    OK = 200
    NOT_FOUND = 404

These values are shared and do not change per instance.

Class methods as alternative constructors

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def from_string(cls, text):
        name, age = text.split(",")
        return cls(name, int(age))

This pattern is common for parsing files, config values, or API input.

Guard clauses with validation

class User:
    @staticmethod
    def is_valid_age(age):
        return age >= 0

    def __init__(self, name, age):
        if not self.is_valid_age(age):
            raise ValueError("Age must be non-negative")
        self.name = name
        self.age = age

Static methods often support validation logic.

Using cls for inheritance-friendly code

class Animal:
    @classmethod
    def create(cls, name):
        return cls(name)

Using cls(...) instead of Animal(...) means subclasses can inherit the method and still create the correct subclass type.

Keeping helper logic near the model

Developers sometimes place related utility functions inside a class with @staticmethod when the logic is closely tied to that class's purpose.

Common Mistakes

Mistake 1: Modifying a class variable through an instance by accident

class Item:
    count = 0

item1 = Item()
item2 = Item()

item1.count = 5

print(item1.count)  # 5
print(item2.count)  # 0
print(Item.count)   # 0

Why this happens

item1.count = 5 creates a new instance variable on item1. It does not change the class variable.

Better approach

Item.count = 5

or inside a class method:

@classmethod
def set_count(cls, value):
    cls.count = value

Mistake 2: Using mutable class variables unintentionally

class Basket:
    items = []

All instances share the same list, which is often not what beginners expect.

Broken behavior

b1 = Basket()
b2 = Basket()

b1.items.append("apple")
print(b2.items)  # ['apple']

Fix

Use an instance variable if each object needs its own list:

class Basket:
    def __init__(self):
        self.items = []

Mistake 3: Forgetting decorators

class Example:
    def greet():
        return "hello"

Calling Example.greet() may work in some limited cases, but this is unclear and usually wrong for object-oriented design.

Fix

Use @staticmethod if no self or cls is needed:

class Example:
    @staticmethod
    def greet():
        return "hello"

Mistake 4: Using self when cls is needed

class Counter:
    total = 0

    def increment(self):
        self.total += 1

This may create or modify an instance variable instead of changing the shared class value.

Better approach

class Counter:
    total = 0

    @classmethod
    def increment(cls):
        cls.total += 1

Mistake 5: Using @staticmethod when inheritance-aware construction is needed

If a method needs to create objects of the current class, use @classmethod, not @staticmethod.

class Person:
    @classmethod
    def anonymous(cls):
        return cls("Anonymous")

Comparisons

ConceptUses self?Uses cls?Access instance data?Access class data?Common use
Instance methodYesNoYesYesWork with one object
Class methodNoYesNoYesShared behavior, alternate constructors
Static methodNoNoNoNo, unless referenced manuallyUtility function related to class

Class variable vs instance variable

FeatureClass variableInstance variable
Belongs toThe classOne object
Shared?YesNo
Defined where?In class bodyUsually in __init__ with self
Typical useConstants, counters, configPer-object state

@classmethod vs @staticmethod

Feature@classmethod@staticmethod
First argumentclsNone automatic
Knows which class called it?YesNo
Good for constructors?YesNo
Good for utility helpers?SometimesYes

Quick rule

  • Use an instance method if you need self
  • Use a class method if you need cls
  • Use a static method if you need neither
Take Quiz

Cheat Sheet

Quick reference

Class variable

class MyClass:
    shared_value = 10
  • Shared by all instances
  • Access with MyClass.shared_value
  • Can also be read through instances

Instance variable

class MyClass:
    def __init__(self, value):
        self.value = value
  • Separate for each object

Class method

class MyClass:
    @classmethod
    def my_method(cls):
        return cls
  • Receives the class as cls
  • Useful for shared logic and factory methods

Static method

class MyClass:
    @staticmethod
    def helper(x, y):
        return x + y
  • Receives no automatic first argument
  • Useful for helper functions tied to the class

Rules to remember

  • Python does not use a static keyword for class variables
  • Class variables are defined directly in the class body
  • Use @classmethod when the method needs the class
  • Use @staticmethod when the method needs neither class nor instance
  • Avoid mutable class variables unless sharing is intentional

Common pattern

class User:
    count = 0

    def __init__(self, name):
        self.name = name
        User.count += 1

    @classmethod
    def total_users(cls):
        return cls.count

    @staticmethod
    def valid_name(name):
        return len(name.strip()) > 0

Edge case

This creates an instance attribute, not a class update:

obj.count = 99

To update the class variable, use:

ClassName.count = 99

FAQ

What is the Python equivalent of a static variable?

In Python, the equivalent is usually a class variable, defined directly inside the class body.

How do I create a static method in Python?

Use the @staticmethod decorator:

class Example:
    @staticmethod
    def hello():
        return "hello"

What is the difference between @classmethod and @staticmethod in Python?

A class method receives cls and can access class state. A static method receives no automatic argument and behaves like a regular function stored inside the class.

Can a class method change a class variable?

Yes. That is one of its main uses.

@classmethod
def set_value(cls, value):
    cls.some_value = value

Can an instance access a class variable?

Yes. An instance can read a class variable unless that name is overridden on the instance itself.

Why does changing a class list affect all objects?

Because a mutable class variable, like a list or dictionary, is shared by all instances.

Should I use @staticmethod a lot?

Only when the function clearly belongs with the class but does not need self or cls. Otherwise, a module-level function may be simpler.

Can I call a class method on an instance?

Yes, but conceptually it belongs to the class. It is often clearer to call it on the class name.

Take Quiz

Mini Project

Description

Build a small BankAccount class to practice class variables, class methods, and static methods together. This project demonstrates a realistic pattern: tracking shared information across all accounts, creating objects in different ways, and validating input with helper logic.

Goal

Create a Python class that tracks the number of bank accounts, stores per-account data, and provides a utility method for validating deposit amounts.

Requirements

  • Create a BankAccount class with an account holder name and balance.
  • Add a class variable that counts how many accounts have been created.
  • Add a class method that returns the total number of accounts.
  • Add a static method that checks whether a deposit amount is valid.
  • Add a deposit() instance method that uses the validation logic.
Take Quiz

Keep learning

Related questions

View more