getattr setattr delattr¶
Built-In Functions¶
1. Overview¶
Python provides three powerful built-in functions to dynamically interact with object attributes:
getattr(obj, name[, default])- retrieve attribute valuesetattr(obj, name, value)- set attribute valuedelattr(obj, name)- delete attribute
2. Why Dynamic Access?¶
Dynamic means determined at runtime, not hardcoded:
# Static (fixed) access
person.name = "Alice"
# Dynamic access
attr = "name"
setattr(person, attr, "Alice")
3. Key Use Cases¶
- Generic code that works with any attribute
- Frameworks that don't know class structure ahead of time
- Serialization/deserialization systems
- Configuration-driven applications
- Reflection and metaprogramming
getattr Function¶
1. Basic Syntax¶
value = getattr(obj, 'attr_name')
value = getattr(obj, 'attr_name', default_value)
2. Simple Example¶
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
# Static access
print(p.name) # "Alice"
# Dynamic access
print(getattr(p, 'name')) # "Alice"
print(getattr(p, 'age')) # 30
3. With Default Value¶
# Attribute exists
print(getattr(p, 'name', 'Unknown')) # "Alice"
# Attribute missing - returns default
print(getattr(p, 'email', 'no-email')) # "no-email"
# Without default - raises AttributeError
# print(getattr(p, 'email')) # ❌ AttributeError
setattr Function¶
1. Basic Syntax¶
setattr(obj, 'attr_name', value)
Equivalent to:
obj.attr_name = value
2. Simple Example¶
class Person:
pass
p = Person()
# Static assignment
p.name = "Alice"
# Dynamic assignment
setattr(p, 'age', 30)
setattr(p, 'city', 'New York')
print(p.name) # "Alice"
print(p.age) # 30
print(p.city) # "New York"
3. Dynamic Attribute Names¶
person = Person()
# Set multiple attributes from dictionary
data = {'name': 'Bob', 'age': 25, 'city': 'Boston'}
for key, value in data.items():
setattr(person, key, value)
print(person.name) # "Bob"
print(person.age) # 25
delattr Function¶
1. Basic Syntax¶
delattr(obj, 'attr_name')
Equivalent to:
del obj.attr_name
2. Simple Example¶
class Person:
def __init__(self):
self.name = "Alice"
self.age = 30
p = Person()
print(p.name) # "Alice"
# Delete attribute
delattr(p, 'name')
# Now accessing raises error
# print(p.name) # ❌ AttributeError
3. Conditional Deletion¶
def remove_attribute(obj, attr):
if hasattr(obj, attr):
delattr(obj, attr)
print(f"Deleted {attr}")
else:
print(f"{attr} doesn't exist")
remove_attribute(p, 'age') # Deleted age
remove_attribute(p, 'email') # email doesn't exist
Practical Examples¶
1. Configuration Loading¶
class Config:
pass
def load_config(filename):
config = Config()
with open(filename) as f:
for line in f:
key, value = line.strip().split('=')
setattr(config, key, value)
return config
# config.txt:
# host=localhost
# port=8080
# debug=true
config = load_config('config.txt')
print(config.host) # "localhost"
print(config.port) # "8080"
2. Dynamic Method Calls¶
class Calculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
def multiply(self, a, b):
return a * b
calc = Calculator()
operation = 'add' # from user input
# Get method dynamically
method = getattr(calc, operation)
result = method(5, 3) # 8
3. Object Serialization¶
def to_dict(obj):
"""Convert object attributes to dictionary"""
result = {}
for attr in dir(obj):
if not attr.startswith('_'):
value = getattr(obj, attr)
if not callable(value):
result[attr] = value
return result
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
print(to_dict(p)) # {'age': 30, 'name': 'Alice'}
hasattr Helper¶
1. Check Existence¶
hasattr(obj, name) checks if attribute exists:
class Person:
def __init__(self, name):
self.name = name
p = Person("Alice")
print(hasattr(p, 'name')) # True
print(hasattr(p, 'age')) # False
2. Safe Access Pattern¶
# Instead of try/except
value = getattr(obj, 'attr', None)
# Or check first
if hasattr(obj, 'attr'):
value = getattr(obj, 'attr')
3. Combined Example¶
def safe_get(obj, attr, default=None):
"""Safely get attribute with default"""
if hasattr(obj, attr):
return getattr(obj, attr)
return default
age = safe_get(person, 'age', 0)
Comparison¶
1. Static vs Dynamic¶
| Aspect | Static Access | Dynamic Access |
|---|---|---|
| Syntax | obj.attr |
getattr(obj, 'attr') |
| Speed | Faster | Slightly slower |
| Flexibility | Fixed at write time | Determined at runtime |
| Use case | Known attributes | Generic/framework code |
2. When to Use Each¶
Use static access (obj.attr) when:
- You know the attribute name at coding time
- Performance is critical
- Code clarity is priority
Use dynamic access (getattr/setattr) when:
- Attribute name comes from user input, config, or database
- Writing generic utilities or frameworks
- Need to iterate over arbitrary attributes
- Implementing serialization/deserialization