@property / @classmethod / @staticmethod
@property is a decorator that lets you use a method as a property, allowing you to add logic when accessing class attributes. @classmethod defines a method that receives the class itself (rather than an instance) as its first argument (cls). @staticmethod defines a utility method that does not depend on the class or any instance.
Syntax
class MyClass:
# Property (getter)
@property
def attr_name(self):
return self._attr_name
# Property (setter)
@attr_name.setter
def attr_name(self, value):
self._attr_name = value
# Class method (cls = the class itself)
@classmethod
def class_method(cls, arg):
...
# Static method (no self or cls needed)
@staticmethod
def static_method(arg):
...
Decorator list
| Decorator | Description |
|---|---|
| @property | Defines a method as a property (read-only access by default). |
| @attr_name.setter | Defines a method that runs when a value is assigned to the property. |
| @attr_name.deleter | Defines a method that runs when the property is deleted with the del statement. |
| @classmethod | Defines a method that receives the class itself (cls) as its first argument. |
| @staticmethod | Defines a static method that receives neither self nor cls. |
Sample code
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
"""Returns the temperature in Celsius."""
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Cannot set a temperature below absolute zero.")
self._celsius = value
@property
def fahrenheit(self):
"""Calculates and returns the temperature in Fahrenheit (read-only)."""
return self._celsius * 9 / 5 + 32
# Accessing properties (no method call syntax needed)
t = Temperature(100)
print(t.celsius) # 100
print(t.fahrenheit) # 212.0
t.celsius = 0 # The setter runs here
print(t.fahrenheit) # 32.0
try:
t.celsius = -300 # Raises a validation error
except ValueError as e:
print(e)
class User:
_count = 0
def __init__(self, name, email):
self.name = name
self.email = email
User._count += 1
@classmethod
def get_count(cls):
"""Returns the number of instances created."""
return cls._count
@classmethod
def from_dict(cls, data):
"""Factory method that creates an instance from a dictionary."""
return cls(data['name'], data['email'])
@staticmethod
def is_valid_email(email):
"""Basic email validation (does not depend on the class or instance)."""
return '@' in email and '.' in email
# Using a class method
u1 = User('Tanaka', 'tanaka@example.com')
u2 = User.from_dict({'name': 'Suzuki', 'email': 'suzuki@example.com'})
print(User.get_count()) # 2
# Using a static method (no instance needed)
print(User.is_valid_email('test@example.com')) # True
print(User.is_valid_email('invalid')) # False
Notes
Using @property lets you automatically add validation or conversion logic whenever an instance variable is accessed. Even if you change the internal implementation of a class, external code can still access it using the same property syntax, making it easier to maintain API compatibility.
@classmethod is frequently used as an alternative constructor (factory method). A common pattern is defining a from_dict() method that creates an instance from a dictionary or JSON data.
@staticmethod is used for logic that belongs to the class conceptually but does not use any class or instance state. If a method uses neither self nor cls, marking it as a staticmethod makes it clear that it belongs in the class scope rather than outside the class.
If you find any errors or copyright issues, please contact us.