Python getattr Function
Last modified April 11, 2025
This comprehensive guide explores Python's getattr function, which
provides dynamic attribute access. We'll cover basic usage, default values,
method calling, and practical examples of dynamic attribute lookup.
Basic Definitions
The getattr function returns the value of a named attribute of an
object. If the attribute doesn't exist, it returns the default value or raises
an AttributeError.
Key characteristics: takes an object, attribute name string, and optional default value. It's Python's built-in way to access attributes dynamically at runtime.
Basic Attribute Access
Here's simple usage showing how getattr can access object
attributes just like dot notation but with dynamic attribute names.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
# Standard attribute access
print(p.name) # Alice
# Using getattr
print(getattr(p, 'name')) # Alice
print(getattr(p, 'age')) # 30
This example shows equivalent ways to access attributes. The getattr
version allows the attribute name to be determined at runtime as a string.
While dot notation is preferred for known attributes, getattr
enables dynamic attribute lookup which is powerful for flexible code.
Handling Missing Attributes
getattr can provide a default value when an attribute doesn't
exist, preventing AttributeError exceptions. This example demonstrates safe
attribute access.
class Config:
def __init__(self):
self.theme = "dark"
self.font_size = 12
config = Config()
# Safe access with default
print(getattr(config, 'theme', 'light')) # dark (exists)
print(getattr(config, 'language', 'en')) # en (default)
print(getattr(config, 'font_size', 14)) # 12 (exists)
When the attribute exists, getattr returns its value. When it
doesn't exist, it returns the default value instead of raising an error.
This pattern is useful for configuration systems where missing settings should fall back to defaults without crashing the program.
Dynamic Method Calling
getattr can retrieve methods dynamically, enabling runtime
determination of which method to call. This example shows polymorphic behavior.
class Calculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
def execute(self, operation, a, b):
method = getattr(self, operation)
return method(a, b)
calc = Calculator()
print(calc.execute('add', 5, 3)) # 8
print(calc.execute('subtract', 5, 3)) # 2
The execute method uses getattr to dynamically select
which operation method to call based on the operation name string.
This technique is common in command pattern implementations and plugin systems where behavior is determined at runtime.
Accessing Nested Attributes
getattr can be combined with other Python features to access nested
attributes dynamically. This example shows deep attribute access.
class Address:
def __init__(self, city):
self.city = city
class User:
def __init__(self, name, address):
self.name = name
self.address = address
addr = Address("New York")
user = User("Bob", addr)
# Dynamically access nested attribute
attr_path = 'address.city'
parts = attr_path.split('.')
result = user
for part in parts:
result = getattr(result, part)
print(result) # New York
This code splits a dotted attribute path and uses getattr in a
loop to traverse nested objects. It's similar to how Django's ORM works.
For production code, you'd want to add error handling for missing attributes at any level in the path.
Implementing Fallback Mechanisms
getattr can be used to implement sophisticated fallback mechanisms
when combined with __getattr__. This example shows a proxy pattern.
class DataProxy:
def __init__(self, data):
self._data = data
def __getattr__(self, name):
# Try to get from _data first, then use default
try:
return getattr(self._data, name)
except AttributeError:
return f"Default {name}"
class Data:
def __init__(self, value):
self.value = value
data = Data(42)
proxy = DataProxy(data)
print(proxy.value) # 42 (from _data)
print(proxy.unknown) # Default unknown
The proxy first tries to get attributes from the wrapped object, then falls
back to a default value. This demonstrates getattr's role in
Python's attribute lookup chain.
This pattern is useful for decorators, adapters, and other proxy objects that need to forward most attribute access.
Best Practices
- Prefer direct access: Use dot notation when attribute names are known
- Use for dynamism: Use getattr when attribute names are determined at runtime
- Provide defaults: Always consider using the default parameter for safety
- Combine with hasattr: Check existence first if default isn't appropriate
- Document behavior: Clearly document dynamic attribute access patterns
Source References
Author
List all Python tutorials.