October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk4 min

Dynamic Attribute Management in Python: Getting, Setting, and Controlling Attributes

A practical guide to Python runtime attribute access, fallback hooks, descriptors, and choosing between objects, dataclasses, runtime models, and mappings.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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:

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choosing between attributes, mappings, and declared schemas

The clearest representation depends on when field names are known and how much structure they need:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

A practical decision rule

  • Only the name is dynamic: use getattr, setattr, or delattr.
  • A missing read should compute or retrieve a fallback: use __getattr__ and raise AttributeError when no value exists.
  • Every read needs interception: consider __getattribute__, delegating ordinary lookup to object.__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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.