setattr()
Dot assignment when the attribute name is a string — useful for dynamic dispatch and configuration.
Common call
setattr(obj, name, value)
Returns
None — the attribute is set on the object
Replaces
the getattr with try/except pattern when writing rather than reading
Watch out
built-in types (str, int, list) are IMMUTABLE — assignment raises TypeError
setattr(objectobject — The object to modify. Instances of user classes accept setattr; built-in types like int, str, list reject it.type: Any · required, namename — The attribute name as a STRING. Not the identifier — a runtime value.type: str · required, valuevalue — The value to assign. Any type. Overwrites any existing attribute with the same name.type: Any · required)
→ None
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| object | Any | yes | The object to modify. Instances of user classes accept setattr; built-in types like int, str, list reject it. |
| name | str | yes | The attribute name as a STRING. Not the identifier — a runtime value. |
| value | Any | yes | The value to assign. Any type. Overwrites any existing attribute with the same name. |
Return value
None — Returns None. Sets the attribute `name` on `object` to `value` — equivalent to `object.name = value` when the name is known at runtime. Raises TypeError when the target is an immutable built-in type; raises AttributeError when the object cannot accept the attribute (e.g. __slots__ classes).
Common patterns
Dynamic attribute assignment
When the attribute name comes from data — config, user input, deserialization.
for key, value in config.items(): setattr(obj, key, value)
Populate a namespace from a dict
Common in constructors that accept **kwargs.
def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v)
Method injection (patching)
Add a method to an existing class at runtime.
def new_method(self): return 42 setattr(MyClass, "answer", new_method)
Prefer dot access for literal names
When the name is known at compile time, plain assignment is clearer.
obj.name = "Alice" # clearer setattr(obj, "name", "Alice") # only if "name" is a variable
Examples
1. Basic
class C: pass
c = C()
setattr(c, "x", 1)
c.x
Returns
12. Overwrite existing
c.x = 1
setattr(c, "x", 99)
c.x
Returns
993. Method injection
setattr(C, "greet", lambda self: "hi")
C().greet()
Returns
"hi"4. Built-in rejects
setattr(str, "foo", 1)
Returns
TypeError: cannot set 'foo' attribute of immutable type 'str'5. Non-string name
setattr(obj, 42, "x")
Returns
TypeError: attribute name must be string, not 'int'6. __slots__ rejects
class P:
__slots__ = ("x",)
p = P()
setattr(p, "y", 1)
Returns
AttributeError: 'P' object has no attribute 'y'Pitfalls
1. Built-in immutable types REJECT setattr
You cannot add attributes to str, int, list, dict, tuple, or any other built-in type. Attempting it raises TypeError with a clear message. Only user-defined classes (and their instances) accept setattr.
Built-in refused
setattr(str, "foo", 1)
TypeError: cannot set 'foo' attribute of immutable type 'str'
Subclass first
class MyStr(str): pass setattr(MyStr, "foo", 1)
works
2. __slots__ classes only accept declared attributes
A __slots__ class has no __dict__ and rejects setattr for undeclared names. Attempts raise AttributeError, not TypeError.
__slots__ refused
class P: __slots__ = ("x",) setattr(P(), "y", 1)
AttributeError: 'P' object has no attribute 'y'
Declare in slots
class P: __slots__ = ("x", "y") setattr(P(), "y", 1)
works
3. Name must be a string
A common typo — passing a non-string as the attribute name. Python rejects it up front.
Non-string name
setattr(obj, 42, "x")
TypeError: attribute name must be string, not 'int'
Quote the name
setattr(obj, "42", "x")
works — sets attr "42"
4. Silently overwrites — no warning
setattr replaces existing attributes without any check. Combined with the dynamic-string form, this makes it easy to accidentally clobber. Guard with hasattr if you care.
Silent clobber
setattr(obj, name, new) # even if obj.name already exists
old value gone
Guard first
if not hasattr(obj, name): setattr(obj, name, new)
explicit intent
When to use
Use it
- Dynamic attribute assignment with a runtime name
- Configuring an object from a dict or kwargs
- Method injection (monkey-patching) — rare in modern code but occasionally useful
- Any place `obj.name = value` is needed but `name` is a variable
Reach for something else
- You have a literal attribute name → use dot access
- The target is a built-in type → cannot be modified
- You want deletion → delattr
- You want to check first → hasattr + setattr, or just try/except
Notes
Complexity
O(1) for a __dict__ assignment; O(mro) if descriptors are involved
Return
None
CPython impl
Python/bltinmodule.c :: builtin_setattr — calls PyObject_SetAttr
Memory
May allocate slots in __dict__
Thread-safe
Depends on whether the underlying attribute access is safe
FAQ
Because built-in types (int, str, list, ...) are implemented in C and their layouts are fixed — no Python-level __dict__ exists. Attempting to add an attribute raises TypeError. Subclass the type if you need to attach attributes.
History
1.0
setattr() has been a builtin since Python 1.0.