Die Python-Funktion setattr(obj, name, value) setzt ein Attribut auf einem Objekt — der Attribut-Name wird als String übergeben und kann damit zur Laufzeit aus einer Variable, einer Konfiguration oder einer Eingabe stammen. Sie ist das Schreib-Pendant zu getattr() und wird dort eingesetzt, wo obj.attr = value nicht passt, weil der Name nicht zur Schreibzeit feststeht.
Einleitung
Im normalen Python-Code schreibt man obj.attr = value — der Attribut-Name ist Teil der Syntax. setattr(obj, "attr", value) macht dasselbe, der Name ist aber ein String und damit dynamisch.
Anwendungsfälle:
- Konfigurations-Loading: Werte aus YAML/JSON in Klassen-Attribute kopieren.
- Plugin-/DSL-Systeme: Klassen oder Module zur Laufzeit aufbauen.
- Property-Forwarding in Adaptern und Dekoratoren.
- Tests/Mocks: Attribute eines fremden Objekts gezielt überschreiben.
Wie bei getattr() werden Properties, Descriptors und __setattr__-Hooks korrekt berücksichtigt. Wer eine Klasse mit __slots__ hat, kann nur die dort definierten Attribute setzen — sonst AttributeError.
Syntax
setattr(object, name, value)object Beliebiges Python-Objekt (Instanz, Klasse, Modul). Muss „setbar" sein — bei Builtins wie int, str ist Setzen nicht möglich.
name Name des Attributs als String.
value Beliebiger Wert.
Rückgabewert
None. setattr() ist nur wegen des Seiteneffekts (Schreiben) interessant.
Beispiele
Standard-Verwendung
Der direkte Vergleich zeigt, was setattr() mit einem dynamischen Namen bringt:
class User:
pass
u = User()
# Statisch:
u.name = "Michael"
# Dynamisch:
for field, value in [("age", 34), ("city", "Berlin")]:
setattr(u, field, value)
print(u.name, u.age, u.city)Michael 34 BerlinKonfiguration in eine Klasse laden
Beim Laden von externen Konfig-Dateien ist setattr() die natürlichste Wahl, weil die Schlüssel erst zur Laufzeit feststehen:
class Config:
pass
data = {"host": "localhost", "port": 8080, "ssl": False}
cfg = Config()
for key, value in data.items():
setattr(cfg, key, value)
print(cfg.host, cfg.port, cfg.ssl)localhost 8080 FalseKlassen-Attribute statt Instanz-Attribute
setattr() funktioniert auch mit Klassen-Objekten — die Änderung gilt dann für alle Instanzen:
class Status:
mode = "idle"
setattr(Status, "version", "1.0")
print(Status.mode, Status.version)idle 1.0Praktische Beispiele
Builder-Pattern mit setattr
Ein einfaches Builder-Pattern lässt sich mit setattr() ohne Duplikat-Code in einer einzigen Schleife bauen:
class Request:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def __repr__(self):
attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"Request({attrs})"
r = Request(method="GET", url="/api/users", timeout=30)
print(r)Request(method='GET', url='/api/users', timeout=30)Methoden zur Laufzeit injizieren
Klassen können auch Methoden via setattr() bekommen — nützlich für Plugins oder beim Bauen von DSLs:
class Calculator:
pass
def add(self, a, b):
return a + b
setattr(Calculator, "add", add)
c = Calculator()
print(c.add(3, 4))7Property zur Laufzeit ergänzen
Mit setattr() und property() lässt sich sogar eine Property nachträglich an eine Klasse hängen:
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
setattr(Person, "fullname", property(lambda self: f"{self.first} {self.last}"))
p = Person("Michael", "Belokon")
print(p.fullname)Michael BelokonPraktische Hinweise
- Statisches
obj.attr = valueist immer schneller alssetattr()— letzteres nur nutzen, wenn der Name dynamisch ist. __slots__-Klassen akzeptieren nur die in__slots__deklarierten Namen — sonstAttributeError.- Builtin-Typen wie
int,strlassen sich nicht modifizieren —setattr(42, "x", 1)schlägt fehl. - Custom
__setattr__in der Klasse wird auch vonsetattr()getriggert. - Verwandte Funktionen:
getattr(),delattr(),hasattr(),vars()(zeigt__dict__).