Last modified April 11, 2025
This comprehensive guide explores Python's setattr function, which
dynamically sets attributes on objects. We'll cover basic usage, dynamic object
manipulation, and practical examples of attribute assignment.
The setattr function assigns a value to an object's attribute. It
takes three parameters: the object, attribute name (string), and value to assign.
Key characteristics: works with any Python object, enables dynamic attribute
assignment, and is equivalent to obj.attr = value but more flexible.
Here's simple usage showing how setattr assigns attributes to an
object, equivalent to direct assignment but with dynamic attribute names.
class Person: pass p = Person() # Equivalent to p.name = 'John' setattr(p, 'name', 'John') # Equivalent to p.age = 30 setattr(p, 'age', 30) print(p.name) # John print(p.age) # 30
This example demonstrates basic setattr usage. We create a simple
Person class and dynamically add attributes. The function call is equivalent to
direct attribute assignment.
The key difference is that setattr allows the attribute name to be
determined at runtime, while direct assignment requires knowing the name at
write time.
setattr shines when attribute names are dynamic or come from
external sources. This example shows dynamic attribute creation from a dict.
class Settings:
pass
config = {
'theme': 'dark',
'font_size': 14,
'auto_save': True
}
settings = Settings()
for key, value in config.items():
setattr(settings, key, value)
print(settings.theme) # dark
print(settings.font_size) # 14
print(settings.auto_save) # True
This example dynamically creates attributes on a Settings object from a configuration dictionary. The attribute names and values come from the dict.
This pattern is useful when loading configurations or converting data structures to objects with attribute access. It's more flexible than hardcoding attributes.
setattr can also modify built-in type instances, though some
built-ins are immutable. This example shows working with mutable objects.
# Works with custom classes
class Box:
pass
b = Box()
setattr(b, 'contents', 'books')
print(b.contents) # books
# Works with some built-in types
d = {}
setattr(d, 'description', 'storage dict')
print(d.description) # storage dict
# Won't work with immutable types like int
try:
x = 5
setattr(x, 'description', 'number')
except AttributeError as e:
print(f"Error: {e}") # can't set attributes of built-in/extension type 'int'
This example shows setattr working with custom classes and some
built-in mutable types. However, immutable types like integers don't support
dynamic attribute assignment.
The error demonstrates that Python prevents modifying built-in types that weren't designed for dynamic attribute assignment.
This example demonstrates using setattr in __init__
to dynamically initialize object attributes based on input parameters.
class DynamicObject:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def __repr__(self):
attrs = ', '.join(f"{k}={v}" for k, v in self.__dict__.items())
return f"DynamicObject({attrs})"
obj = DynamicObject(name='Alice', age=25, city='London')
print(obj) # DynamicObject(name=Alice, age=25, city=London)
print(obj.name) # Alice
print(obj.age) # 25
The DynamicObject class accepts arbitrary keyword arguments and converts them
to attributes using setattr. This creates a flexible object that
can have any attributes specified at creation time.
This pattern is useful for creating data containers or when the exact attributes aren't known when writing the class. It's similar to how JavaScript objects work.
This advanced example shows how setattr interacts with properties
and descriptors, respecting Python's attribute access protocol.
class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero")
self._celsius = value
@property
def fahrenheit(self):
return self._celsius * 9/5 + 32
temp = Temperature(25)
# Uses the property setter
setattr(temp, 'celsius', 30)
print(temp.celsius) # 30
# Can't set read-only property
try:
setattr(temp, 'fahrenheit', 100)
except AttributeError as e:
print(f"Error: {e}") # can't set attribute
# Respects property validation
try:
setattr(temp, 'celsius', -300)
except ValueError as e:
print(f"Error: {e}") # Temperature below absolute zero
This example demonstrates that setattr properly interacts with
Python's property system. It calls property setters when available and respects
read-only properties.
The validation in the celsius setter is triggered by setattr,
showing it follows the same attribute access rules as direct assignment.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Python tutorials.