Python __getattr__ Method

Complete guide to Python's __getattr__ method covering dynamic attribute access, fallback mechanisms, and proxy patterns.

Python __getattr__ Method

Python getattr Method

Last modified April 8, 2025

This comprehensive guide explores Python’s getattr method, the special method for handling attribute access. We’ll cover basic usage, dynamic attributes, fallback mechanisms, proxy patterns, and practical examples.

Basic Definitions

The getattr method is called when an attribute lookup fails. It serves as a fallback mechanism for attribute access. The method takes the attribute name as argument and should return a value or raise AttributeError.

Key characteristics: it’s only called for missing attributes, can dynamically compute values, and is part of Python’s attribute access protocol. It differs from getattribute which intercepts all attribute access.

Basic getattr Implementation

Here’s a simple implementation showing how getattr works as a fallback for missing attributes. It demonstrates the basic syntax and behavior.

basic_getattr.py

class DynamicAttributes: def getattr(self, name): if name == ‘color’: return ‘blue’ raise AttributeError(f"‘DynamicAttributes’ has no attribute ‘{name}’")

obj = DynamicAttributes() print(obj.color) # ‘blue’

print(obj.size) # Raises AttributeError

This example shows getattr handling requests for undefined attributes. When ‘color’ is accessed, it returns ‘blue’. Other names raise AttributeError as recommended.

The method receives the attribute name as a string. You can implement any logic to compute or fetch the value. Always raise AttributeError for invalid names.

Dynamic Attribute Computation

getattr can compute attributes dynamically based on patterns or naming conventions. This is useful for APIs with predictable attribute names.

dynamic_computation.py

class DynamicCalculator: def getattr(self, name): if name.startswith(‘calc_’): operation = name[5:] def calculator(*args): return f"Calculated {operation} of {args}" return calculator raise AttributeError(f"No such attribute: {name}")

calc = DynamicCalculator() print(calc.calc_sum(1, 2, 3)) # “Calculated sum of (1, 2, 3)” print(calc.calc_product(4, 5)) # “Calculated product of (4, 5)”

This class dynamically creates calculation methods based on attribute names starting with ‘calc_’. The returned functions use the operation name in their output.

The example demonstrates how getattr can create and return functions on demand. This pattern is used in many ORMs and API wrappers.

Lazy Attribute Loading

getattr can implement lazy loading of expensive resources, fetching them only when first accessed and caching for future use.

lazy_loading.py

class LazyLoader: def init(self): self._cache = {}

def __getattr__(self, name):
    if name not in self._cache:
        print(f"Loading {name}...")
        self._cache[name] = f"Value of {name}"
    return self._cache[name]

loader = LazyLoader() print(loader.data1) # “Loading data1…” then “Value of data1” print(loader.data1) # “Value of data1” (from cache)

This implementation loads attributes only when first accessed and stores them in a cache dictionary. Subsequent accesses return the cached value.

The pattern is useful for expensive operations like database connections or file loading. It optimizes performance by deferring work until needed.

Proxy Pattern Implementation

getattr can forward attribute access to another object, implementing the proxy pattern. This is useful for wrappers and decorators.

proxy_pattern.py

class Proxy: def init(self, target): self._target = target

def __getattr__(self, name):
    return getattr(self._target, name)

class Target: def init(self, value): self.value = value def method(self): return f"Target method: {self.value}"

target = Target(42) proxy = Proxy(target) print(proxy.value) # 42 print(proxy.method()) # “Target method: 42”

The Proxy class forwards all attribute access to its target object using getattr. This creates a transparent wrapper around the target.

Proxies can add behavior before/after forwarding calls. This pattern is used in mock objects, remoting, and access control systems.

Dictionary-like Attribute Access

getattr can provide dictionary-like access to data while maintaining object syntax. This creates a hybrid object-dictionary interface.

dict_access.py

class DictLikeObject: def init(self, data): self._data = data

def __getattr__(self, name):
    if name in self._data:
        return self._data[name]
    raise AttributeError(f"No attribute or key '{name}'")

data = {’name’: ‘Alice’, ‘age’: 30, ‘city’: ‘London’} obj = DictLikeObject(data) print(obj.name) # ‘Alice’ print(obj.age) # 30

print(obj.job) # Raises AttributeError

This class wraps a dictionary and exposes its keys as attributes. It combines dictionary storage with object access syntax.

The implementation checks the dictionary before raising AttributeError. This pattern is used in configuration systems and JSON object wrappers.

Best Practices

  • Raise AttributeError for missing attributes: Follow Python’s convention

  • Keep it simple: Complex logic can make code hard to debug

  • Document dynamic attributes: Help users know what’s available

  • Consider performance: getattr is slower than regular attributes

  • Use dir: Implement dir to help with introspection

Source References

Author

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.

ad ad