Explain Codes LogoExplain Codes Logo

Class (static) variables and methods

python
class-variables
instance-attributes
descriptor-protocol
Nikita BarsukovbyNikita Barsukov·Aug 5, 2024
TLDR

In Python, class variables are shared attributes between all instances, similar to static variables in some other languages. You can modify these variables using @classmethod. Access class variables with ClassName.variable and within class methods, use cls.variable:

class MyClass: counter = 0 @classmethod def increase_counter(cls): cls.counter += 1 # Call class method to increment the counter MyClass.increase_counter() print(MyClass.counter) # Output: 1
<!-- Add a touch of humor here --> <!-- Who knew counters could be this fun? -->

Static methods, on the other hand, neither modify nor use the class or instance state. Achieve this procedure with the @staticmethod decorator:

class MyClass: @staticmethod def my_static_method(): print('This is a static method.') MyClass.my_static_method() # Calls the static method
<!-- Come on, it's not tomb of Tutankhamun, it's just a static. Say it out loud! -->

Remember, class variables can be accessed through the class (ClassName.variable) or an instance. However, always make modifications at the class level to prevent shadowing and to ensure sync across all instances.

Understand the specifics

Class vs instance attributes

In Python, understanding the behaviour of mutable and immutable types is vital when dealing with class and instance variables. Typically, an immutable class variable remains the same unless explicitly redefined at the class level. However, mutable class variables (like lists or dictionaries) can lead to unpredictable side effects.

Dynamic attributes

Python being a dynamic language supports runtime attribute attachment. Adding instance variables on the fly might lead to discrepancies between instances, which shows the flexibility —and trouble!— Python's classes offer.

a = MyClass() b = MyClass() a.dynamic_var = 10 # If 'a' had a nickel for every dynamic variable, it'd have a nickel.

Class variable synchronization

In some advanced cases, you might need synchronised static variables across threads, consider using a custom metaclass like StaticVarsMeta. Remember, with great power comes great complexity!

class StaticVarsMeta(type): _shared_state = {} def __init__(cls, name, bases, attrs): super().__init__(name, bases, attrs) cls._shared_state.update(attrs) cls.__dict__ = cls._shared_state

More code tools for exploration

Understanding class internals

You can explore Python's __dict__ attribute to differentiate between class and instance variables:

print(MyClass.__dict__) # Prints class attributes: "If attributes attended a masquerade, __dict__ would be the chaperone." print(a.__dict__) # Prints instance-specific attributes

Shadowing occurs when an instance variable with the same name as a class variable is encountered. Always ensure you access or modify class variables via ClassName.variable.

Control access to attributes

Understanding and using Python's descriptor protocol and @property provides control over access and modification to attributes.

class MyClass: _read_only = 'Read Only' @property def read_only(self): return self._read_only
<!-- A small joke here --> <!-- It's 'Read Only', don't even try to write on it. Seriously, don't. -->