Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallWhen an attribute name is computed at runtime, use Python’s built-ins: getattr(obj, name[, default]) to read it, setattr(obj, name, value) to assign it, and delattr(obj, name) to delete it. For a name written directly in your code, ordinary obj.name syntax is clearer. If you need validation, fallback behavior, or a runtime-defined schema, choose a mechanism designed for that job rather than routing every operation through dynamic attributes.
How to get, set, or delete an attribute by name
Pass the attribute name as a string. These built-ins perform the equivalent of ordinary attribute operations while letting the name come from configuration, input, or another runtime value:
name = "timeout"
value = getattr(settings, name, 30) # use 30 if the attribute is missing
setattr(settings, name, 45)
delattr(settings, name)
The third argument to getattr is optional. When provided, it is returned if the attribute is unavailable; without it, a missing attribute raises AttributeError. setattr and delattr can invoke customized assignment or deletion behavior, so they do not necessarily write to or remove an entry from an instance dictionary.
Python does not support expression-based attribute syntax such as obj.(name). That syntax appeared in the rejected PEP 363 proposal; use getattr, setattr, and delattr instead.
Recommended Free Tools
#1 Best Overall
When to use __getattr__ or __getattribute__
Both customize reads, but they run at different points. Define __getattr__(self, name) when you want to supply a computed value only after normal lookup fails. Define __getattribute__(self, name) only when every instance attribute read must be intercepted. It runs unconditionally, so careless use can cause infinite recursion.
Provide a fallback only for missing attributes
A fallback can expose values stored in a separate mapping as attribute-style reads:
Rank #2
class Settings:
def __init__(self, values):
self._values = values
def __getattr__(self, name):
try:
return self._values[name]
except KeyError:
raise AttributeError(name) from None
When the mapping has no matching key, raising AttributeError correctly signals that the requested attribute is unavailable. Keep unrelated failures visible: converting every exception into a missing-attribute result can hide bugs in the fallback logic.
Intercept every read only when necessary
Because __getattribute__ runs for every instance read—including reads performed inside the method itself—use object.__getattribute__(self, name) for ordinary lookup rather than accessing self.name recursively. The Python 3.14.8 data model reference documents the lookup hooks and their behavior.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Assignment and deletion have separate hooks: __setattr__ controls assignments, and __delattr__ controls deletions. Preserve normal behavior for names your customization does not intend to change.
When a descriptor is a better fit than setattr
setattr is the right tool for a one-off assignment whose name is known only at runtime. A descriptor is more suitable when the same access rule—such as validation, conversion, lazy computation, or indirect storage—should apply consistently to a field across instances or classes. A property is a convenient managed attribute; descriptors are the underlying protocol used by properties and other Python features.
Attribute lookup is not simply a check of obj.__dict__. For a typical instance, Python checks a data descriptor, then the instance dictionary, then a non-data descriptor, then a class variable, and finally the __getattr__ fallback if lookup still fails. A data descriptor defines __set__ or __delete__ and takes precedence over a same-named instance entry. A non-data descriptor defines only __get__, so an instance entry can override it. Consequently, assigning obj.x may be governed by a descriptor or custom __setattr__, rather than directly changing obj.__dict__. See the Python descriptor HOWTO for the protocol and its lookup rules.
Choosing between attributes, mappings, and declared schemas
The clearest representation depends on when field names are known and how much structure they need:
Best Value
| Situation | Good fit | Why |
|---|---|---|
| A single attribute name is computed at runtime | getattr, setattr, or delattr |
Use the built-in operation for the dynamic name. |
| Missing reads need a fallback | __getattr__ |
Normal lookup remains intact; the hook runs only after it fails. |
| Every instance read needs custom handling | __getattribute__ |
It intercepts all instance reads, but requires careful delegation. |
| A shared field rule should manage reads or writes | A descriptor or property |
The rule is attached to attribute access rather than repeated at each call site. |
| Fields are known when the class is defined | An ordinary class or dataclass |
Declared fields make the object’s shape explicit to readers and tools. |
| The schema arrives at runtime | A runtime model, such as Pydantic’s create_model() |
Model fields can be built from runtime definitions. |
| Values are open-ended and routinely enumerated by key | A dictionary | Mapping syntax communicates a collection of arbitrary keys directly. |
Use a dataclass for a declared set of fields
Dataclasses inspect annotated class variables to find fields and generate methods on the class. A descriptor assigned as a field default continues to receive attribute get and set calls. Setting frozen=True generates assignment and deletion methods that raise FrozenInstanceError; this emulates protection against reassignment, rather than making an instance absolutely immutable. The Python dataclasses documentation describes these behaviors.
Use a runtime model when the schema itself is dynamic
Pydantic’s create_model() builds models from field definitions assembled at runtime. Pydantic models ignore extra input by default, and configuration can instead allow or forbid extra fields. Those are Pydantic model policies, not rules of Python’s attribute system. Check the Pydantic dynamic model creation documentation for the version you use.
Prefer a mapping for unbounded keys
If callers need to add, inspect, and enumerate arbitrary user-provided keys, a dictionary is often a clearer interface than turning each key into an object attribute. Dynamic attribute names can make an object harder to inspect, validate, type-check, and document. Attribute syntax is most useful when names form a meaningful object interface, even if some operations choose those names at runtime.
Quick Recap
A practical decision rule
- Only the name is dynamic: use
getattr,setattr, ordelattr. - A missing read should compute or retrieve a fallback: use
__getattr__and raiseAttributeErrorwhen no value exists. - Every read needs interception: consider
__getattribute__, delegating ordinary lookup toobject.__getattribute__. - The same access rule belongs on several fields: use a descriptor or property.
- The field set is fixed: declare it in a class or dataclass; if field definitions arrive at runtime, use a runtime-model facility.
- The keys are arbitrary collection entries: use a dictionary rather than manufacturing an attribute interface.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.




