Explain Codes LogoExplain Codes Logo

Difference between 'cls' and 'self' in Python classes?

python
object-oriented-programming
self-reference
class-reference
Alex KataevbyAlex Kataev·Feb 4, 2025
TLDR

In a nutshell, self is the instance itself—it's used in instance methods to access or modify the object's state. cls, on the other hand, stands for the class itself and is employed in class methods (those equipped with the @classmethod decorator) to adjust class traits shared across all instances.

Instance method using self:

class MyClass: def greet(self): return f'Hello from instance {id(self)}'

Class method using cls:

class MyClass: @classmethod def identify(cls): return f'Hello from the class: {cls.__name__}'

Remember self talks about the instance, cls refers to the class.

The nitty-gritty behind the arguments

The self:

  • Involved in object creation: When you instantiate an object with __init__.
  • Accesses attributes: If you want to access or mutate any variables that belong to your instance.
  • Facilitates internal calls: When a method needs to call another within the same object.

The cls:

  • Crafts Factory methods: For methods that give life to instances of the class.
  • Alter Class state: To change class-level variables influencing every instance.
  • Encourages class awareness: In scenarios where methods applicable to subclasses.

When it comes to code readability and maintainability, PEP 8 vouches for using self and cls—the more consistency in your code, the better.

Diving deeper into Python magic

Class-level machinations with cls

Factories, anyone? That's right, cls as a parameter can wield class methods to churn out product lines i.e., instances.

class Pizza: @classmethod def create(cls, size=None, toppings=None): # Don't you dare pass both arguments as None! if size is None or toppings is None: raise ValueError("No pizza size or toppings mentioned. Order not made!") return cls(size, toppings)

Object-level customization with self

Pointing to the instance, self is your one-man army for customizing instances. The following snippet shows how self embodies instances:

class Car: def paint(self, color): self.color = color # my car, my rules! return f'The car is now {self.color}'

Knowing cls for Subclasses

cls is a bit more social—it's aware of subclasses. It references whichever class the employed method belongs to, which is super handy for inheritance hierarchies:

class Parent: @classmethod def whoami(cls): return f"I am the Class: {cls.__name__}" class Child(Parent): pass print(Child.whoami()) # Output: I am the Class: Child

Freedom with Conventions

Even though self and cls are conventional, it's the position that nails them as self-references or class-references:

class Confusion: def method(instance): # Flying in the face of convention. But hey, it works! print(instance) @classmethod def anothermethod(klass): # "klass" not "class", because the latter's a keyword, remember? print(klass)

Contextualizing usage

Class vs. Instance level modifications

For modifications speaking to the class state, use cls. For changes affecting only the current object, call on self. Knowing the difference makes for extensible code.

Static methods—the third wheel

Besides cls in class methods, we also have @staticmethod decorator. Unlike @classmethod, it takes neither self nor cls. Neutral to both class and instance states, it's best for utility functions.

Method overriding—redefining tasks

With cls, subclass methods can override superclass methods for tailored behavior while ensuring a link to the superclass version through super().

Practical scenarios

cls and self are the two sides of the same coin adding versatility to Python:

  • cls—the key opener for singleton patterns by controlling instance creation.
  • self—the enabler for fluent interfaces by letting methods return self for method chaining.
  • Together they clear the API for instance-specific and class-wide functions.

Mastering these and more, you're ready to sail the Python's object-oriented paradigm.